Skip to content

feat(web): pasting a huge screenshot now compresses it instead of erroring - #4967

Merged
t3dotgg merged 2 commits into
mainfrom
t3code/compress-large-pasted-images
Jul 30, 2026
Merged

feat(web): pasting a huge screenshot now compresses it instead of erroring#4967
t3dotgg merged 2 commits into
mainfrom
t3code/compress-large-pasted-images

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Jul 30, 2026

Copy link
Copy Markdown
Member

Pasting or dropping an image over 10MB into the composer just failed with "exceeds the 10MB attachment limit" — annoying for big retina screenshots that would survive compression with no meaningful quality loss.

Now oversized images are downscaled and re-encoded (WebP, JPEG fallback) to fit under the 10MB wire cap, reusing the same pipeline that already compresses images for the prompt stash. stashImageCompression.ts became the shared imageCompression.ts with a new compressImageToByteLimit entry point; stash behavior is unchanged. Images already under the cap still pass through byte-for-byte.

Sources over 50MB are refused outright — file size is a proxy for pixel count, and decoding something that large into an ImageBitmap risks OOMing the tab.

Web only: mobile's paste path has no canvas and keeps its existing 10MB reject.

Written by Claude Fable 5 via Claude Code.

🤖 Generated with Claude Code


Note

Medium Risk
Changes user-facing send/attach behavior and runs canvas decode/re-encode on large pastes in the main composer path; failures are handled but wrong timing could still strand attachments or block send unexpectedly.

Overview
Pasting or dropping images larger than the provider wire cap no longer fails with a size error — they are downscaled and re-encoded (WebP/JPEG) to fit under PROVIDER_SEND_TURN_MAX_IMAGE_BYTES, while files already under the cap still attach byte-for-byte.

stashImageCompression is consolidated into shared imageCompression.ts: stash behavior stays on compressImageForStash, and compressImageToByteLimit returns a re-encoded File for the composer. A shared reencodeWithinBudget loop handles both paths; sources above MAX_COMPRESSIBLE_SOURCE_BYTES (50MB) are refused without decoding to avoid tab OOM.

addComposerImages is now async: it reserves attachment slots via a per-thread pending compression counter (so concurrent pastes respect the limit), compresses each accepted file, then updates preview/name/type from the result. submitComposer blocks send while compression is in flight and shows an info toast so a turn snapshot cannot miss an in-progress paste.

Reviewed by Cursor Bugbot for commit e765e2c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Compress oversized pasted or dropped images instead of rejecting them

  • Adds compressImageToByteLimit in imageCompression.ts that downscales and re-encodes image files to WebP/JPEG to fit the provider wire cap (PROVIDER_SEND_TURN_MAX_IMAGE_BYTES); files already within the limit pass through unchanged.
  • Updates ChatComposer.tsx to compress pasted/dropped images asynchronously rather than hard-rejecting oversized ones.
  • While compression is in progress, sending is blocked and an info toast prompts the user to send again once the thumbnail appears.
  • Attachment slot reservation accounts for in-flight compressions so concurrent pastes cannot exceed the per-turn attachment cap.
  • Sources above MAX_COMPRESSIBLE_SOURCE_BYTES are refused without decoding to avoid memory issues. Risk: users who previously received an error for large images will now see a delay before the compressed image appears.

Macroscope summarized e765e2c.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 246a558c-8691-4a15-a4fb-f5b835050fed

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

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 30, 2026
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx
@macroscopeapp

macroscopeapp Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces new feature behavior (compressing oversized images instead of rejecting them) with async state management and race condition handling. Additionally, there are two unresolved medium-severity review comments identifying potential bugs in the error clearing and slot reservation logic.

You can customize Macroscope's approvability policy. Learn more.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e765e2c. Configure here.

Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/chat/ChatComposer.tsx
@t3dotgg
t3dotgg merged commit cbe8052 into main Jul 30, 2026
17 checks passed
@t3dotgg
t3dotgg deleted the t3code/compress-large-pasted-images branch July 30, 2026 11:35
tarik02 added a commit to tarik02-org/t3code that referenced this pull request Jul 30, 2026
* fix(desktop): restore T3 Connect sign-in (pingdotgg#4809)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* Simplify files panel header (pingdotgg#4828)

* build(desktop): reduce installed app size by ~300MB (pingdotgg#4824)

* Update model version from claude-opus-4-8 to claude-opus-5 (pingdotgg#4832)

* Preserve the thread shell while detail loads (pingdotgg#4830)

* Reduce idle work and disk churn with native resource diagnostics (pingdotgg#2679)

Co-authored-by: codex <codex@users.noreply.github.com>

* fix(server): detect repositories after initialization (pingdotgg#4848)

* perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat (pingdotgg#4843)

* fix(git): disable external diff for review diff previews (pingdotgg#4854)

* Fix editable file focus and live syntax highlighting (pingdotgg#3979)

* fix(web): remember the rendered-markdown choice across threads (pingdotgg#4853)

Co-authored-by: Simon Doba <simon.doba@orbit.de>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* chore(release): prepare v0.0.31

* fix(mobile): reduce thread feed scroll jank (pingdotgg#4874)

* fix(web): restore sidebar v2 thread actions and terminal icon (pingdotgg#4712)

* fix(web): settle button now works on hover, not just right-click (pingdotgg#4905)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(clients): disable add project while disconnected (pingdotgg#4834)

* fix(composer): hide default Codex service tier (pingdotgg#4784)

* docs: link iOS and Android app store downloads (pingdotgg#4902)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(web): align remote server update action (pingdotgg#4731)

* fix(connect): suggest a serve command that matches how you ran connect (pingdotgg#4897)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(mobile): stop shared content errors in Personal Team builds (pingdotgg#4943)

* perf(mobile): sends respond instantly, thread opens stop freezing (pingdotgg#4882)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(web): show Codex fast mode as a bolt (pingdotgg#4947)

* docs: seed worktrees with a copy of real userdata instead of banning it (pingdotgg#4949)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(mobile): support dragged images in the composer (pingdotgg#4953)

* fix(mobile): stop long iOS threads from jumping while scrolling up (pingdotgg#4867)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(web): keep worktree default when switching a draft's machine (pingdotgg#4964)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* perf(mobile): reconnect environments immediately on resume (pingdotgg#4878)

* feat(web): pasting a huge screenshot now compresses it instead of erroring (pingdotgg#4967)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* feat(web): regenerate thread titles from sidebar (pingdotgg#4810)

* fix(web): show server update progress through reconnect (pingdotgg#4903)

---------

Co-authored-by: Alex <me@pixp.cc>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: wukko <me@wukko.me>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Wout Stiens <71498452+StiensWout@users.noreply.github.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: ohbentos <72638975+ohbentos@users.noreply.github.com>
Co-authored-by: Jake Leventhal <jakeleventhal@me.com>
Co-authored-by: Simon Doba <simon.doba@hotmail.de>
Co-authored-by: Simon Doba <simon.doba@orbit.de>
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
Co-authored-by: Gabriel De Andrade <30420087+gabrielelpidio@users.noreply.github.com>
Co-authored-by: Jono Kemball <Noojuno@users.noreply.github.com>
Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Max Katz <me@maxkatz.me>
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Jul 30, 2026
## What's Changed
* fix(mobile): support dragged images in the composer by @t3dotgg in pingdotgg/t3code#4953
* fix(mobile): stop long iOS threads from jumping while scrolling up by @t3dotgg in pingdotgg/t3code#4867
* fix(web): keep worktree default when switching a draft's machine by @t3dotgg in pingdotgg/t3code#4964
* perf(mobile): reconnect environments immediately on resume by @t3dotgg in pingdotgg/t3code#4878
* feat(web): pasting a huge screenshot now compresses it instead of erroring by @t3dotgg in pingdotgg/t3code#4967
* feat(web): regenerate thread titles from sidebar by @t3dotgg in pingdotgg/t3code#4810
* fix(web): show server update progress through reconnect by @t3dotgg in pingdotgg/t3code#4903
* feat(search): find threads by conversation content by @t3dotgg in pingdotgg/t3code#4959
* fix: marketing site Vercel builds no longer die after ~100 deploys by @t3dotgg in pingdotgg/t3code#4975


**Full Changelog**: pingdotgg/t3code@v0.0.32-nightly.20260730.955...v0.0.32-nightly.20260730.956

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32-nightly.20260730.956
juliusmarminge added a commit that referenced this pull request Jul 30, 2026
27 commits from main, including the ⌘P file picker / ⇧⌘F content search
(#4855), thread content search (#4959), sidebar title regeneration
(#4810), image-paste compression (#4967), and the docs restructure
(#4807). Notable resolutions beyond keep-both:

- Thread content search is ported to the v2 surface: searchThreads joins
  ORCHESTRATION_V2_WS_METHODS/rpc/auth scopes, and the SQL now UNIONs
  orchestration_v2_projection_messages so current threads are searchable,
  not just legacy-projected ones.
- Title regeneration's server half lived in the v1 ProviderCommandReactor
  this branch deletes, so the capability is deliberately not advertised:
  clients hide the action, the contract/UI code stays intact, and the
  input field is accepted as a documented no-op.
  TODO(orchestration-v2): port regeneration to the v2 runtime.
- Main's 035_ProjectionThreadTitleRegeneration migration collided with
  this branch's 035-043 range; renumbered to 044.
- Mobile activity grouping keeps this branch's runId/prominence semantics
  while adopting main's O(1) trailing-group optimization (prominence
  tracked in a flag instead of a per-append scan).
- v1-only startup tests from main (heartbeat/auto-bootstrap against the
  deleted reactor-era services) are dropped; their v2 equivalents already
  cover the ordered startup phases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). 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