fix(web): render local images inline - #5114
Conversation
AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a new feature enabling inline rendering of local workspace images. It adds new user-facing behavior with a new component that fetches signed asset URLs, touches multiple layers (server projection, web rendering, clipboard handling), and warrants human review to verify the integration across these components. You can customize Macroscope's approvability policy. Learn more. |
Use the preserved activity detail when nested provider image data is removed during transport projection. Add regression coverage for the projected production payload shape. Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Reject non-path image detail summaries and recover projected structured image paths before rendering. Preserve original Markdown image sources when copying so signed asset URLs do not leave the app. Addresses pingdotgg#5114 (comment) Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Add integration coverage for the existing Windows work-log image path flow. This changes no production behavior; it confirms that Markdown URL sanitization already preserves the decoded path for signed asset requests. Documents pingdotgg#5114 (comment) as a false positive. AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Add clipboard coverage proving that percent-encoded Windows image paths resolve back to the original workspace path. This changes no production behavior and confirms the copied Markdown remains functional. Documents pingdotgg#5114 (comment) as a false positive. AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
|
Tested this PR locally and it fixed the issue for me. Environment: Ubuntu 24.04.4 LTS (Debian-based), x86_64, kernel 7.0.0-28-generic, T3 Code AppImage. I built PR head Both local Markdown images and |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3ec9e15. Configure here.
Preserve structured savedPath values in projected item data so generated images still render when the human-readable activity detail is truncated. Addresses pingdotgg#5114 (comment) AI-Assisted: true AI-Agent: codex AI-Model: openai/gpt-5.6-sol
Upstream be1a836, 54 commits. Both carried pull requests (pingdotgg#4989 mermaid, pingdotgg#5114 inline images) are still open upstream, so this is a plain merge rather than the reset-and-replay that a landed pull request forces. Five files conflicted across eight hunks: ActivityPayloadProjection.ts: dropStaleRateLimitActivities (local) and dropSupersededToolUpdatedActivities (upstream b7d1981) were inserted at the same point. Independent filters, so both are kept and composed. ClaudeAdapter.ts: upstream pingdotgg#5557 fixes the same interrupt bug as the local 4429c29, and fixes it better. It reads the CLI's own terminal_reason field rather than tracking an interrupt flag across the session, and separately filters [ede_diagnostic] strings out of the error banner. Upstream's version is taken and all nine pieces of the local fix are reverted, along with the two tests that covered the reverted implementation. The third test in that group, which asserts a genuine failure still reports as an error, passes against upstream's fix and is kept. Local plan-usage work in the same file is untouched. ChatView.tsx: the local turnInterruptionNotice and upstream's new turnPlans argument collided on one call. deriveTimelineEntries takes both, so both are passed. ComposerPendingUserInputPanel.tsx: local collapsible chrome versus upstream's theme library restyle (85b1734). Upstream's change to this file is five className token swaps and nothing structural, so the local structure is kept and the five swaps applied to it. pnpm-lock.yaml: regenerated on upstream's lockfile; mermaid re-added. Verified: web 1983 tests pass, web and server typechecks clean. The server suite fails 30 files / 116 tests on Windows, which is pre-existing and not from this merge. Every failing file was compared against the pre-merge tree: 27 fail identically, 2 more outside src/ fail identically, one test in ProviderRegistry that failed before now passes, and the only new failures are 3 brand new upstream tests in cloud/http.test.ts that hit a pre-existing Windows incompatibility (fsync on a directory handle in serviceLauncher.ts, from upstream pingdotgg#5181, already present in the base). Upstream CI runs Ubuntu and macOS only, so this suite has never been green on Windows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Problem
Local workspace images referenced in chat Markdown render as broken placeholders, even though the same paths work as file links. Image generation and
view_imagealso provide local paths that were not surfaced as visible image output.Fixes #2398.
Fix
file://workspace image sources through T3 Code's existing signed asset URLs.imageGeneration.savedPathandimageView.pathlifecycle data and render those outputs inline in the work log.This reuses the existing workspace asset boundary: paths are resolved against the thread workspace and served through expiring signed URLs instead of exposing raw local-file URLs.
Screenshots
The screenshots for generated image output and workspace images rendered through Markdown were captured with a local development build and will be attached separately.
Validation
pnpm exec vp test run apps/web/src/markdown-links.test.ts apps/web/src/session-logic.test.ts apps/server/src/provider/Layers/CodexAdapter.test.ts— 122 tests passedpnpm exec vp run --filter @t3tools/web typecheckpnpm exec vp run --filter t3 typecheckview_imageyou can see the before in the linked issue
Checklist
🤖 Implementation and tests were generated with OpenAI Codex (GPT-5.6 Sol) through the T3 Code Codex harness, then reviewed and verified in a local development build.
Note
Low Risk
UI and asset-display changes reusing the existing signed workspace-file boundary; no auth or persistence changes.
Overview
Fixes broken local image placeholders by routing workspace image paths through the existing signed asset URL flow instead of raw
file:URLs.Chat Markdown adds
resolveMarkdownImageFileLinkMetaand aMarkdownWorkspaceImagecomponent that resolves relative, absolute, andfile://image sources against the thread workspace. The sanitize schema now allowsfile:onimgsrc; remote images are unchanged.Work log derives an
imagePathonimage_viewentries from CodexsavedPath/path, Claude file lists, and image-like details, then renders inline previews under the row viaChatMarkdown. Server keepssavedPathin activity payload projection and maps CodexsavedPathinto lifecycle detail.Clipboard stores the original markdown source on
data-markdown-srcso copy/paste round-trips workspace paths (including encoded Windows paths) rather than expiring signed URLs.Reviewed by Cursor Bugbot for commit b9f2090. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Render local workspace images inline in chat work log entries
MarkdownWorkspaceImagecomponent in ChatMarkdown.tsx that resolves workspace file paths to signed asset URLs and renders them inline, with loading/error fallbacks.SimpleWorkEntryRowin MessagesTimeline.tsx to display an inline image whenworkEntry.imagePathis set and athreadRefis available.imagePathtoWorkLogEntryin session-logic.ts, derived fromitem.savedPath,item.path,changedFiles, orpayload.detailforimage_viewactivities.data-markdown-src) rather than signed URLs when copying images.ActivityPayloadProjectionto retainsavedPaththrough payload projection so image paths survive to the frontend.Macroscope summarized b9f2090.