fix(web,mobile): chat images reload when the agent rewrites the file#29741

merged4
main
t3/fix-stale-image-cache
opened21h agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 17h ago

When an agent regenerates an image under the same path (for example a script that rewrites wau.png on every run) and shows it again, the chat keeps showing the old picture. Chat images get one signed URL per path, and the browser caches that URL for an hour. The file preview panel already got a new URL whenever the workspace changed, but chat images never received that signal. Users worked around it by writing a new filename on every run, which breaks the image in every earlier message.

Fix

  • Chat images in the timeline now receive the thread's workspace mutation id through a context, on web/desktop (WorkspaceMutationIdContext) and mobile (WorkspaceMutationIdProvider around ThreadFeed). Each host image fetches a fresh URL after the agent touches the workspace. Only the image components re-render.
  • The mutation id now also changes after MCP/dynamic tool calls and subagents, which can write files without reporting their paths. Before, only commands and file edits counted.
  • When a fresh URL reports the same fileRevision, the image keeps its current URL, so unchanged images are not downloaded again after every command. It still switches once the shown URL is within 5 minutes of expiring.
  • deriveWorkspaceMutationId (plus a new workspaceMutationIdAtom) and makeRevisionedAssetUrlFamily moved to client-runtime so web and mobile share them. Because the atom's value is a string, the feed re-renders only when the id changes, not on streamed text.

Verification

I ran a real Claude Haiku thread in the web dev build. Each turn ran node render.mjs <red|blue>, which rewrites wau.png, and then embedded it:

  • Before (pre-fix client code): after turn 3 rewrote the file to red, all three chat images still showed the previous blue (pixel 30,90,230) under an unchanged URL.
  • After (this branch): after turn 4 rewrote the file to blue, every chat image switched to blue under a newly minted URL, live and without a reload.

Before: wau.png is red on disk but the chat still shows the stale blue

After: the agent rewrote wau.png to blue and every chat image updated live

Tests: a case in packages/client-runtime/src/state/assets.test.ts (an unchanged file keeps its URL, a changed one swaps; fails without the fix) and an MCP-tool row in the deriveWorkspaceMutationId test. Mobile was not exercised on a device.

Most of the ChatView.tsx and ThreadDetailScreen.tsx diffs are re-indentation from the new wrappers.

Done by Claude Opus 5.5 in Claude Code.

šŸ¤– Generated with Claude Code

Checks

21 successful Ā· 19 skipped
All checks passed
7024cab

Added 1 commit

  • fix(web,mobile): chat images reload when the agent rewrites the file581ebe9
Synced from GitHub

Approvability

Verdict: Approved at 54cd718

Macroscope's review found this PR approvable — This change refreshes workspace-backed chat images on web and mobile while retaining URLs for unchanged files. Its effects are limited to display caching and read refreshes; the reported unnecessary-reload finding remains covered by the separate blocking gate.

Notes:

  • This verdict was updated automatically after the outstanding correctness findings were resolved. Macroscope did not re-review the code.

No code changes detected at 7024cab. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between c5ad8e1ca70293d45683d2536caf5479198e8833 and 7024cabfbc4c113f55ba23782fa0342f243e9804.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

The client runtime now derives workspace mutation IDs and provides revision-keyed asset URL state. Web and mobile chat media pass those IDs when requesting URLs for eligible media.

Changes: Revision-aware chat media

Layer / File(s)Summary
Workspace mutation ID derivation
packages/client-runtime/src/state/threadDetail.ts, packages/client-runtime/src/state/threadDetail.test.ts, apps/web/src/components/ChatView.logic.ts, apps/web/src/components/ChatView.logic.test.ts
The runtime derives an ID from the latest completed qualifying workspace item and checkpoint timestamp. The former web-local helper and its tests are removed.
Revision-keyed asset URL state
packages/client-runtime/src/state/assets.ts, packages/client-runtime/src/state/assets.test.ts, apps/mobile/src/state/assets.ts, apps/web/src/assets/assetUrls.ts, apps/web/src/assets/assetUrls.test.ts
The runtime adds a revision-keyed URL family and tests. Web uses the runtime implementation in place of its local one. Mobile asset URL state accepts an optional revision.
Mutation ID context and media integration
apps/web/src/components/ChatView.tsx, apps/web/src/components/chat/ChatMarkdownMedia.tsx, apps/mobile/src/features/threads/ThreadDetailScreen.tsx, apps/mobile/src/features/threads/ThreadMarkdownImage.tsx, apps/mobile/src/features/threads/WorkspaceMutationIdProvider.tsx, apps/mobile/src/features/threads/workspaceMutationIdContext.ts
Web and mobile provide the thread mutation ID to media rendering. Eligible media passes the ID to asset URL state.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix Ā· Severity of issue fixed: Low

Sequence Diagram(s)

mermaid
1sequenceDiagram
2 participant ThreadDetailAtoms
3 participant ChatView
4 participant WorkspaceMutationIdContext
5 participant ChatMarkdownAssetImage
6 participant useAssetUrlState
7 participant RevisionedAssetUrlFamily
8 ThreadDetailAtoms->>ChatView: derive workspace mutation ID
9 ChatView->>WorkspaceMutationIdContext: provide ID
10 WorkspaceMutationIdContext->>ChatMarkdownAssetImage: supply ID
11 ChatMarkdownAssetImage->>useAssetUrlState: pass eligible media revision
12 useAssetUrlState->>RevisionedAssetUrlFamily: select revision-keyed URL atom
13 RevisionedAssetUrlFamily->>RevisionedAssetUrlFamily: mint or refresh URL

Possibly related issues

  • Issue 15676: The change adds revision-aware URL refresh for overwritten images that may otherwise display older cached content.
  • Issue 27681: The change passes workspace mutation IDs to media URL state for revision-based refresh behavior.
  • Issue 13138: The change adds revision-aware URL refresh for image previews after source files are overwritten.

Suggested labels: bugfix

Suggested reviewers: t3dotgg, maria-rcks

Merge Risk: External image Minimal Ā· previous review 54cd7

The change makes chat images refresh after an agent rewrites a file, and no concrete merge-blocking defect was established. An Electron reconnect that changes the local media base URL remains unconfirmed and is worth a quick check by the author.

Pre-merge checks: Passed 3 Ā· Failed 1

Failed Failed checks: 1 warning

Check nameStatusExplanationResolution
Description checkWarningThe description follows the template. It covers the problem (chat images keep a stale URL when an agent rewrites a file at the same path), the change (context wrappers on web and mobile, broader mutat…Add a Scope and approval section. Link the triaged bug issue or the maintainer discussion that approved this direction, with the approval comment. If no issue exists, explain why this focused fix of an obvious bug qualifies without prior ap…
Passed Passed checks: 3 passed
Check nameStatusExplanation
Title checkPassedThe title names the main change: chat images reload when the agent rewrites a file at the same path. The changeset adds a workspace mutation ID context for chat images on web and mobile, and a revisio…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: chat images reload when the agent rewrites a file at the same path. The changeset adds a workspace mutation ID context for chat images on web and mobile, and a revisioned asset URL family that mints fresh URLs after workspace changes. The title follows conventional commit format and is specific, so it passes.

Full details: Description check

Explanation

The description follows the template. It covers the problem (chat images keep a stale URL when an agent rewrites a file at the same path), the change (context wrappers on web and mobile, broader mutation tracking, revision-based URL reuse, and code moved to client-runtime), and verification (a real-thread manual test with before and after screenshots, plus a named unit test and an MCP-tool test case). The author states that mobile was not exercised on a device. The Scope and approval section is missing. It should link the triaged bug issue or maintainer-approved discussion, or explain why this small fix qualifies without one. The PR also adds a new shared atom and moves shared logic to client-runtime, so the scope justification matters here.

Resolution

Add a Scope and approval section. Link the triaged bug issue or the maintainer discussion that approved this direction, with the approval comment. If no issue exists, explain why this focused fix of an obvious bug qualifies without prior approval. Also state how the broader mutation tracking (MCP/dynamic tool calls and subagents) and the move of shared logic into client-runtime fall within that scope.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix Ā· Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 581ebe9bbe17928edb9cdc44a0feeb795fb2beb1 and 54cd71829287d83bd45a60530b17a0cfd55e1dbf.

External image Files selected for processing: 2
  • packages/client-runtime/src/state/assets.test.ts
  • packages/client-runtime/src/state/assets.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Added 1 commit

  • fix(client-runtime): keep an unchanged image's URL across revisions54cd718
Synced from GitHub

Thread transfer impact

āš ļø The latest CI run did not produce a thread transfer result for c5ad8e1.

This comment will update automatically after the next completed run.

Added 2 commits

  • Merge remote-tracking branch 'origin/main' into t3/fix-stale-image-cachec5ad8e1
  • Merge remote-tracking branch 'origin/main' into t3/fix-stale-image-cache7024cab