Skip to content

feat: let agents work with PDFs, ZIPs, and other files - #8092

Open
t3dotgg wants to merge 7 commits into
mainfrom
t3code/generic-file-uploads
Open

feat: let agents work with PDFs, ZIPs, and other files#8092
t3dotgg wants to merge 7 commits into
mainfrom
t3code/generic-file-uploads

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Aug 24, 2026

Copy link
Copy Markdown
Member

T3 Code only accepted image attachments. PDFs, ZIP archives, and large text files had no direct route to an agent.

Web, desktop, and mobile can now upload files up to 50 MB directly to their environment. Agents receive the saved file path, images keep their existing behavior, and mobile supports the system file picker and share sheet.

Uploads stream to disk, pending files reuse hard links, and downloaded documents cannot run as pages.

The mobile share-sheet change requires a new iOS and Android store build before later OTA updates work.

Built with GPT-5.6 Sol in the Codex harness.


Note

High Risk
Touches signed upload tokens, streamed attachment storage, asset download headers, and mobile share-sheet MIME handling—security-sensitive file ingest and serving paths.

Overview
Agents can now receive generic files (PDFs, ZIPs, etc.), not just images. Servers advertise a fileAttachments capability with a 50 MB upload cap; images keep the existing 10 MB path.

Web and mobile composers pick, persist, and upload files alongside images. Mobile copies files into app-owned storage, cleans them when drafts/outbox no longer reference them, and accepts files from the share sheet (*/* on Android; iOS file share counts). File picking is gated on the server capability.

Uploads stream to disk instead of buffering the whole body. Attachment IDs can encode a safe extension so files resolve without directory scans. Pending uploads are claimed with a hard link (copy fallback). Document downloads force Content-Disposition: attachment and a sandbox CSP so they cannot execute as pages.

Providers still get images as attachments; files are injected as on-disk path lines in the turn text. Legacy image upload tokens remain valid. Mobile share-sheet MIME changes need a new store build before later OTAs.

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

Note

Add support for non-image file attachments (PDFs, ZIPs) across web, mobile, and server

  • Introduces a ChatFileAttachment type and fileAttachments environment capability (50 MB max) in packages/contracts/src/orchestration.ts, expanding ChatAttachment beyond images
  • Web composer (apps/web/src/components/chat/ChatComposer.tsx) supports attaching, uploading, retrying, and removing generic files; drafts and prompt stash persist file references without file bytes
  • Mobile composer and sharing pipeline (apps/mobile/src/lib/composerImages.ts, apps/mobile/src/features/sharing/incoming-share-model.ts) can pick, persist, upload, and clean up generic files via expo-file-system
  • Server (apps/server/src/assets/AttachmentUpload.ts, apps/server/src/attachmentStore.ts) issues typed upload URLs, streams file bodies to disk preserving file extensions, enforces signed byte limits, and serves file assets with Content-Disposition: attachment headers
  • Providers (apps/server/src/provider/Layers/ProviderService.ts) receive only image attachments in the routed input array; file attachments are referenced via path hints in the input text rather than forwarded as image content
  • Risk: AttachmentUploadClaims schema adds a type field defaulting to 'image' for legacy tokens — verify all existing upload token decoders handle the new field; attachmentIdExtensionSuffix appends -bin for invalid/missing extensions, so attachment IDs now have a different shape than before

Macroscope summarized d014010.

@coderabbitai

coderabbitai Bot commented Aug 24, 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: bf5c8e9c-a404-4b53-8676-35938904f407

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:XXL 1,000+ changed lines (additions + deletions). 📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. labels Aug 24, 2026
@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.4 KiB 13.4 KiB +1 B (+0.0%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB 0 B (0.0%) 7.3 KiB
Codex Live turn WebSocket wire 6.5 KiB 6.5 KiB +1 B (+0.0%) 7.8 KiB
Codex Live turn WebSocket decoded 55.0 KiB 55.0 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 16 16 0 (0.0%) 21
Claude Total thread wire 13.5 KiB 13.5 KiB +6 B (+0.0%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB +1 B (+0.0%) 7.3 KiB
Claude Live turn WebSocket wire 6.6 KiB 6.6 KiB +5 B (+0.1%) 7.8 KiB
Claude Live turn WebSocket decoded 55.8 KiB 55.8 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 16 16 0 (0.0%) 21

Baseline: f035a0f · PR result: d014010 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.4 KiB
  • Claude decoded thread snapshot: 110.1 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Comment thread apps/web/src/composerDraftStore.ts Outdated
Comment thread apps/mobile/src/features/threads/new-task-flow-provider.tsx Outdated
Comment thread apps/mobile/src/features/threads/new-task-flow-provider.tsx Outdated
Comment thread apps/server/src/assets/AttachmentUpload.ts Outdated
Comment thread apps/mobile/src/lib/composerImages.ts
Comment thread apps/mobile/src/lib/composerImages.ts Outdated
Comment thread apps/web/src/composerDraftStore.ts
Comment thread apps/mobile/src/features/sharing/incoming-share-model.ts
Comment thread apps/mobile/src/features/threads/new-task-flow-provider.tsx Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This change introduces end-to-end file attachments across web and mobile, including new upload protocols, server-side storage and download handling, provider path integration, draft persistence, and cleanup workflows. Its cross-platform scope and substantial runtime/storage side effects require human review.

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

@macroscopeapp macroscopeapp 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.

One UI consistency finding in the new web composer file attachment row. Everything else in the changed web scope (the paperclip Button size="icon-sm" + Tooltip/TooltipTrigger render composition, the icon-xs retry/remove actions, the timeline download anchor, and the semantic color tokens used) matches the existing composer/timeline conventions.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/mobile/src/features/threads/new-task-flow-provider.tsx Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
Comment thread apps/mobile/src/features/threads/use-project-actions.ts Outdated

@macroscopeapp macroscopeapp 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.

One finding in the changed web UI: the new attachment download link inside the user message bubble hovers to text-primary, which is the solid-control fill role rather than a foreground role owned by the message surface. Details inline. (The unbounded retry tooltip in ChatComposer.tsx file rows from the earlier review is still open; not re-posting it.)

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/chat/MessagesTimeline.tsx Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx

@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 3 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 ae250e2. Configure here.

Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/composerDraftStore.ts Outdated

@macroscopeapp macroscopeapp 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.

One new finding in scope, plus one carried-over finding that is still unresolved.

New: the stashed-file count badge in ComposerStashMenu does not pin a type scale or an icon tone, so it renders larger than every sibling metadata span in the row and its icon is re-colored by the CommandItem primitive. Inline comment below.

Still open from a previous run (not re-posted): apps/web/src/components/chat/MessagesTimeline.tsx:1075 — the file download link on the user message bubble takes its hover color from --primary, which index.css defines as the solid-control fill role rather than a text role owned by the bg-message surface, so the hover state is not guaranteed to stay legible in themed palettes. A message-surface-owned foreground (e.g. the existing text-message-foreground with an opacity/underline hover) keeps the hover state under the surface that renders it.

Everything else in the changed web UI looks consistent: the new composer attach control uses Button variant="ghost" size="icon-sm" inside the standard Tooltip/TooltipTrigger render composition, the failed-upload tooltip now matches the image tile's max-w-64 whitespace-normal leading-tight cap, and the attach affordance is correctly gated out of the collapsed-mobile and approval footers.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/chat/ComposerStashMenu.tsx

@macroscopeapp macroscopeapp 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.

UI consistency review of the changed web files. Two findings, both about draft/stash surfaces that summarize composer attachments and were not updated for the new files list. The previously flagged message-link hover token and the uncapped retry tooltip in ChatComposer are both resolved in this revision.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/chat/ComposerStashMenu.tsx Outdated
Comment thread apps/web/src/composerDraftStore.ts
@baptisteArno

Copy link
Copy Markdown

YES

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. size:XXL 1,000+ 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.

2 participants