Skip to content

feat(server): accept PDF, ZIP, and other file uploads up to 50MB - #8235

Merged
t3dotgg merged 7 commits into
mainfrom
t3code/file-attachments-server
Aug 28, 2026
Merged

feat(server): accept PDF, ZIP, and other file uploads up to 50MB#8235
t3dotgg merged 7 commits into
mainfrom
t3code/file-attachments-server

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Aug 25, 2026

Copy link
Copy Markdown
Member

T3 Code currently accepts only image attachments. This PR adds the server contract, streaming
upload, storage, and download support for generic files up to 50 MiB. The web and mobile file
pickers remain separate in #8236 and
#8237.

Each provider adapter chooses which attachments it sends as native inputs. The prompt includes the
real path for every attachment, so unsupported native inputs still reach the agent as paths.

The takeover fixes interrupted upload cleanup, returns HTTP 400 for unfinished oversize uploads
instead of resetting the socket, encodes extended download filenames correctly, keeps mobile from
rendering files as images before its file UI ships, and corrects the rollback documentation.

Compatibility warning: the tolerant schema only helps updated clients. Older clients cannot decode
messages with file attachments. Older servers can also fail startup for the whole environment when
event replay reaches a file-bearing message. Do not treat rollback as a per-thread failure.

Theo Browne wrote the original implementation with Claude Fable 5 in Claude Code. The original
commit authorship and co-author trailers are preserved.

Built with GPT-5.6 Sol in the Codex harness.


Note

Medium Risk
Touches attachment auth tokens, streaming upload I/O, and download response headers (XSS via mime/disposition), plus persisted event schemas—version skew can break whole-environment replay on rollback.

Overview
Adds generic file attachments (PDF, ZIP, etc.) alongside images: contracts expose ChatFileAttachment, type: "file" upload URLs (50 MiB cap), and environment capability fileAttachments.maxUploadBytes. Upload and storage stream bodies to .part files with size enforcement and cleanup on failure or interrupt; attachment IDs can carry a sanitized extension suffix so paths resolve without directory scans. Downloads bake download, fileName, and mimeType into signed asset tokens and serve attachment disposition, sandbox CSP, and vetted Content-Type (HTML/XML/SVG forced to octet-stream).

Provider turns append an on-disk path line for every attachment; image-only adapters skip non-images for native input while OpenCode sends supported PDFs/text/images under a size cap. Projection and cleanup handle file attachments; mobile thread feed shows images only until file UI ships; web gains isImageAttachment so file members typecheck without image-only UI.

Compatibility: tolerant ChatUnknownAttachment decoding on messages; legacy upload tokens default to image; older clients/servers and file-bearing persisted events remain a documented skew risk.

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

Note

Add support for generic file uploads up to 50MB with streaming

  • Adds schemas for ChatFileAttachment and FileAttachmentCreateUploadUrlInput in orchestration.ts and assets.ts to validate generic files up to 50 MiB (PROVIDER_SEND_TURN_MAX_FILE_BYTES)
  • Modifies storeAttachmentUpload in AttachmentUpload.ts to stream uploads to a .part file and enforce size limits, rejecting oversized or mismatched uploads with a 400 status
  • Extends attachment IDs in attachmentStore.ts with a validated file extension suffix (e.g., -pdf) to allow direct path resolution without scanning directories
  • Implements download headers (Content-Disposition, sandbox CSP) and safe mime type validation in http.ts for serving generic files
  • Updates provider adapters in apps/server/src/provider/Layers/ to filter non-image attachments from native image ingestion paths, relying on prompt path lines for generic file access
  • Risk: attachmentRelativePath now returns null for unknown attachment types; ProviderService.sendTurn no longer sets input.attachments to an empty array when absent, so downstream adapters may receive undefined

Macroscope summarized 88b541d.

@coderabbitai

coderabbitai Bot commented Aug 25, 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: ae0e9152-6daa-46d3-a592-6ff68346f32f

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

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 Aug 25, 2026
Comment thread packages/contracts/src/orchestration.ts Outdated
Comment thread apps/server/src/attachmentStore.ts Outdated
Comment thread apps/server/src/http.ts Outdated
@github-actions

github-actions Bot commented Aug 25, 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.3 KiB 13.3 KiB +4 B (+0.0%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB −13 B (−0.2%) 7.3 KiB
Codex Live turn WebSocket wire 6.4 KiB 6.4 KiB +17 B (+0.3%) 7.8 KiB
Codex Live turn WebSocket decoded 55.6 KiB 55.6 KiB +44 B (+0.1%) 66.4 KiB
Codex Live turn messages 10 11 +1 (+10.0%) 21
Claude Total thread wire 13.3 KiB 13.4 KiB +12 B (+0.1%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB +7 B (+0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.5 KiB 6.5 KiB +5 B (+0.1%) 7.8 KiB
Claude Live turn WebSocket decoded 56.4 KiB 56.4 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 11 11 0 (0.0%) 21

Baseline: f276e63 · PR result: 88b541d · 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 packages/contracts/src/orchestration.ts
@macroscopeapp

macroscopeapp Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces generic file uploads and downloads up to 50 MiB, including streaming filesystem I/O, signed download metadata, provider-specific attachment handling, and persisted schema changes. The broad runtime and compatibility impact, plus security-sensitive MIME and browser-disposition behavior, warrants human review.

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

Comment thread apps/server/src/provider/opencodeRuntime.ts Outdated
t3dotgg and others added 6 commits August 28, 2026 01:12
Uploads of any file type now stream through the attachment route with a
byte cap instead of buffering in memory. The chat attachment schema
gains a "file" member plus a catch-all for attachment types from newer
builds, so older readers keep decoding messages instead of failing.
Downloads serve the real filename and Content-Type from the signed
asset claims. Each provider adapter decides what its provider ingests
natively: OpenCode sends generic files as file parts, the others send
images only and rely on the file path added to the turn text.

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

The attachment contract now carries file and unknown members. Web renders images only for now and filters the rest through an isImageAttachment guard, so unknown attachment types degrade to nothing instead of a decode failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The tolerant attachment member no longer accepts the image and file discriminators, so a malformed known attachment fails its own schema instead of bypassing size and mime checks. Files named *.part store as .bin so the stale-upload sweep cannot delete them. Download dispositions survive unpaired surrogates in filenames.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A ZIP sent as a native file part makes OpenCode's Anthropic path throw AI_UnsupportedFunctionalityError before the turn starts, so the file path in the prompt never helps. Images, text, and PDFs stay native; everything else rides as the path line like the other providers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Model APIs reject BMP, AVIF, and SVG image parts, and OpenCode's direct-attachment path caps out at 20 MB. Native file parts are now PNG/JPEG/GIF/WebP, text, and PDF at or under that size; the rest ride as the prompt's file path line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove partial upload files when request streams fail or get interrupted.
Keep chunked requests open until the server sends an oversize response.
Encode extended filenames correctly, skip files in the mobile image renderer,
and document old-client and old-server replay limits.

Built with GPT-5.6 Sol in the Codex harness.
@t3dotgg
t3dotgg force-pushed the t3code/file-attachments-server branch from c669b79 to 826e1e3 Compare August 28, 2026 08:24
Comment thread apps/server/src/http.ts

@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 1 potential issue.

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 826e1e3. Configure here.

Comment thread apps/server/src/http.ts Outdated
Narrow XML download detection so Office Open XML files keep their official
content types while actual XML and SVG content stays octet-stream.

Built with GPT-5.6 Sol in the Codex harness.
@t3dotgg
t3dotgg merged commit 8f49132 into main Aug 28, 2026
28 checks passed
@t3dotgg
t3dotgg deleted the t3code/file-attachments-server branch August 28, 2026 09:05
frankdavidcorona pushed a commit to frankdavidcorona/t3code that referenced this pull request Aug 28, 2026
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 28, 2026
## What's Changed
* fix(codex): show sub-agent models by @t3dotgg in pingdotgg/t3code#8502
* feat(analytics): report connected client platforms by @t3dotgg in pingdotgg/t3code#8481
* feat(server): accept PDF, ZIP, and other file uploads up to 50MB by @t3dotgg in pingdotgg/t3code#8235
* feat(web): toggle a thread's pin from the keyboard by @ipanasenko in pingdotgg/t3code#8440


**Full Changelog**: pingdotgg/t3code@v0.0.36-nightly.20260828.1209...v0.0.36-nightly.20260828.1210

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.36-nightly.20260828.1210
juliusmarminge added a commit that referenced this pull request Aug 28, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
juliusmarminge added a commit that referenced this pull request Aug 28, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
juliusmarminge added a commit that referenced this pull request Aug 29, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 29, 2026
## What's Changed
* fix(grok): improve skills, plans, usage, and turn reliability by @t3dotgg in pingdotgg/t3code#8358
* fix(server): recover stale Codex approval callbacks by @luckyPipewrench in pingdotgg/t3code#5195
* test(server): remove duplicate missing worktree test by @t3-code[bot] in pingdotgg/t3code#8252
* fix(server): replay all un-applied events during projection bootstrap by @krutftw in pingdotgg/t3code#7538
* test: remove low-signal test files by @t3-code[bot] in pingdotgg/t3code#8397
* test: prune trivial error and layout tests by @t3-code[bot] in pingdotgg/t3code#8400
* Fix Android adaptive launcher icon by @colonelpanic8 in pingdotgg/t3code#4332
* feat(web): split provider settings into list and editor by @t3dotgg in pingdotgg/t3code#8380
* fix(codex): accept Codex 0.150 account plans by @gsimone in pingdotgg/t3code#8447
* fix(tooling): allow ignored-only staged changes by @juliusmarminge in pingdotgg/t3code#8468
* fix(mobile): keep iOS home header stable by @juliusmarminge in pingdotgg/t3code#8467
* fix(web): stop showing red x summaries for ordinary tool failures by @t3dotgg in pingdotgg/t3code#8395
* fix(mobile): refine Git action toast glass styling by @juliusmarminge in pingdotgg/t3code#8399
* fix(desktop): allow preview automation in agent-created threads by @t3dotgg in pingdotgg/t3code#8483
* test(web): remove redundant cache key test by @t3-code[bot] in pingdotgg/t3code#8484
* fix(release): move nightly schedule to minute 38 by @t3dotgg in pingdotgg/t3code#8509
* fix(web): stabilize the provider settings editor by @t3dotgg in pingdotgg/t3code#8472
* fix(web): open GitHub pull requests in browser when loading fails by @t3dotgg in pingdotgg/t3code#8507
* fix(codex): show sub-agent models by @t3dotgg in pingdotgg/t3code#8502
* feat(analytics): report connected client platforms by @t3dotgg in pingdotgg/t3code#8481
* feat(server): accept PDF, ZIP, and other file uploads up to 50MB by @t3dotgg in pingdotgg/t3code#8235
* feat(web): toggle a thread's pin from the keyboard by @ipanasenko in pingdotgg/t3code#8440
* fix(web): add back button to project settings by @StiensWout in pingdotgg/t3code#8168
* refactor(mobile): compile semantic themes for Uniwind by @juliusmarminge in pingdotgg/t3code#7327
* fix(desktop): Cache Runtime locally on WSL Filesystem, dramatically improving launch times  by @ikifar2012 in pingdotgg/t3code#5769
* fix(mobile): show OpenCode model sources in picker by @juliusmarminge in pingdotgg/t3code#8573
* fix(clients): honor project default models in new threads by @anirudhsama in pingdotgg/t3code#6011
* fix(mobile): show file actions on Android by @none23 in pingdotgg/t3code#8215
* fix(connect): explain DPoP connection failures by @extoci in pingdotgg/t3code#8351
* feat(web): make the sidebar project filter a searchable combobox by @SunkenInTime in pingdotgg/t3code#5931
* fix(server): a draft can retry its first send after a failed bootstrap by @shivamhwp in pingdotgg/t3code#8226
* fix(desktop): stop hidden previews draining battery by @Bil0000 in pingdotgg/t3code#8567
* fix(desktop): oauth popups open from the browser preview by @walid-baharwal in pingdotgg/t3code#8435
* fix(web): keep long task drawers usable on small screens by @shivamhwp in pingdotgg/t3code#8313
* fix(opencode): handle child approvals, stops, and model catalogs by @t3dotgg in pingdotgg/t3code#8480
* fix: make thread auto-settling opt-in by @shivamhwp in pingdotgg/t3code#8321
* fix(web): stop session activity timing test from blocking releases by @t3dotgg in pingdotgg/t3code#8585
* fix(mobile): show composer menus when starting a task by @juliusmarminge in pingdotgg/t3code#8587
* fix(web): show the configured stash shortcut by @UtkarshUsername in pingdotgg/t3code#8437
* feat(web): add toggleable confirmation before unpinning a thread by @UtkarshUsername in pingdotgg/t3code#7313
* fix: restore automatic thread settling defaults by @t3dotgg in pingdotgg/t3code#8596
* fix(mobile): restore composer glass and rounded shadows by @juliusmarminge in pingdotgg/t3code#8597

## New Contributors
* @luckyPipewrench made their first contribution in pingdotgg/t3code#5195
* @krutftw made their first contribution in pingdotgg/t3code#7538
* @colonelpanic8 made their first contribution in pingdotgg/t3code#4332
* @ikifar2012 made their first contribution in pingdotgg/t3code#5769
* @walid-baharwal made their first contribution in pingdotgg/t3code#8435

**Full Changelog**: pingdotgg/t3code@v0.0.35...v0.0.36

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.36
juliusmarminge added a commit that referenced this pull request Aug 29, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rynfar pushed a commit to pylon-code/pylon that referenced this pull request Aug 29, 2026
Adds the server contract, streaming upload, storage, and download support for
generic files up to 50 MiB. Previously only images were accepted.

Every attachment's absolute path goes into the turn text, and every attachment
now reaches the provider adapter, which decides what its provider ingests
natively. OpenCode sends images, text files, and PDFs up to 20 MB as native file
parts; the other adapters send images only and rely on the path line.

Adopted from T3 Code 8f49132214a40c85cf46bf5e3d8ea11c04a9610a
(pingdotgg/t3code#8235).

Adaptation:

PrimeAgentAdapter needed the image-only guard the other five adapters received.
Upstream has no Prime adapter, and Pylon's pushed every attachment into an ACP
image content block unconditionally - so once ProviderService started forwarding
generic files, a PDF would have been base64'd and sent as an image with
application/pdf as its mime type. Prime runs models on Anthropic and OpenAI
Codex, so images-only matches those providers' own adapters.

Unlike upstream, that guard ships with a test. The mock ACP agent's existing
request log is used to assert the prompt Prime actually sends.

The cherry-pick also dropped ProviderService.test.ts's EnvironmentId import,
which upstream no longer needs but Pylon's browser-credential test still uses.

docs/internals/providers.md keeps Pylon's Subscription capacity section and
gains upstream's Attachment access section, with Prime Agent listed among the
image-only providers.
juliusmarminge added a commit that referenced this pull request Aug 29, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aorwall added a commit to aorwall/t3code that referenced this pull request Aug 29, 2026
Merges 58 upstream commits (`badae6a5c` → `6a9d9f988`, upstream v0.0.34
→ v0.0.36) through the `fork-upstream-merge` skill.

`merge-stats.mjs` reconciles exactly: **431 files landed** against **431
in the upstream range**, no gap to explain. Fork delta is 611 files.

## Conflicts

Three, plus one git resolved silently and wrongly.

- **`Sidebar.tsx`** — upstream replaced the project picker's
`Menu`/`MenuRadioGroup` with a searchable `Combobox` (pingdotgg#5931). Took
upstream's structure and re-applied only the
`FEATURES.projectManagement` gate on "New project", now carrying the `//
Fork:` marker it had been missing. Upstream has since grown the mobile
touch-target span itself, so the Mobile Touch Delta has nothing left to
re-apply here — one convergence, unprompted.
- **`ProviderSettingsPanel.tsx`** — upstream split provider settings
into list and editor (pingdotgg#8380, pingdotgg#8472), moving `ProviderLastChecked` and
the refresh button out of `headerAction` into the list footer. Took
upstream's and re-applied the gate as `!readOnly &&
FEATURES.serverAdministration`.
- **`pnpm-lock.yaml`** — took upstream's and re-ran `vp i`, which
restored the fork's `@t3tools/moatless-api` workspace edge.
- **`packages/contracts/src/orchestration.test.ts`** — auto-merged, no
marker, broken. Both sides appended `OrchestrationMessage` to the same
import list and the same `decodeOrchestrationMessage` const at different
offsets, so git took both. Surfaced as a parse error in lint, typecheck
and test at once. This is the case `merge-stats.mjs`'s
conflict-candidate list exists to catch.

`HostedBrowserFrame.tsx` (fork-only) also needed the `renderingActive`
prop pingdotgg#8567 made required. Upstream suspends a parked webview unless
background audio, PiP or a recording still needs it painted; a frame has
none of those to read and is the app's only copy of the preview page, so
it passes `true` and keeps today's behavior.

## Sweep

Five keyword hits, all false positives:

- `apps/web/src/connection/clientMetadata.ts` + test — reports the
client's OS/browser/device on connect (pingdotgg#8481). Auth-adjacent, but it
rides `ClientPresentation` on the relay and remote-bearer bootstraps;
the fork's primary environment sends none of it.
- `packages/client-runtime/src/relay/errorPresentation.ts` + test,
`connection/errors.test.ts` — explain DPoP failures (pingdotgg#8351). Relay only,
and T3 Connect is decided out.

## Feature classification

**Usable as-is**

- Searchable project-filter combobox in the sidebar (pingdotgg#5931).
- Long task drawers stay usable on small screens (pingdotgg#8313) — directly
relevant, the fork's phone story is `apps/web` in mobile Safari/Chrome.
- Toggleable confirmation before unpinning a thread (pingdotgg#7313); toggle
thread pin from the keyboard.
- Back button in project settings (pingdotgg#8168); the configured stash shortcut
is shown (pingdotgg#8437).
- No more red-x summaries for ordinary tool failures (pingdotgg#8395); PRs open
in the browser when loading fails (pingdotgg#8507).
- Project default models are honored in new threads (pingdotgg#6011).
- Provider settings split into list and editor (pingdotgg#8380, pingdotgg#8472) — landed,
though `/settings/providers` is itself gated behind
`serverAdministration`.

**Unsupported in Moatless / needs implementation**

- **Non-image file attachments** (pingdotgg#8235) — a turn may now carry any file
up to 50MB, advertised as `capabilities.fileAttachments.maxUploadBytes`
and sized by `PROVIDER_SEND_TURN_MAX_FILE_BYTES`. Moatless advertises
neither this nor `attachmentUploads`, so the composer's attach
affordance stays off. Costs nothing today (upstream's own web composer
offers images only; `ChatAttachment` widened just far enough to
typecheck), but it is the second capability key to report when uploads
land. Extends the existing **Attachment uploads** entry in
`docs/fork/gaps.md`.
- **Connected-client platform analytics** (pingdotgg#8481) and **DPoP failure
explanations** (pingdotgg#8351) — relay and T3 Connect surfaces, already decided
out of the fork.

No new WS methods entered the contract in this range, so no new
`UnsupportedMethodError` union entries. `unsupported-methods.mjs`
reports `ADD 0`, `DROP 1` (`scripts.run`), `KEEP 2`. The `scripts.run`
DROP is **not** actioned — it is the documented exception in the gaps
register: that union entry answers for `apps/server`, which still stubs
the method (verified surviving in `ws.ts`), not for Moatless.

**Backend behavior to consider reproducing in Moatless**

- **Replay all un-applied events during projection bootstrap** (pingdotgg#7538) —
a one-line pipeline fix upstream; Moatless runs its own projection and
the same class of bug applies.
- **A draft can retry its first send after a failed bootstrap** (pingdotgg#8226)
— Moatless owns turn start, and a draft wedged by a failed bootstrap is
the same dead end here.
- **Recover stale Codex approval callbacks** (pingdotgg#5195) — Moatless owns the
agent runtime in the sandbox.
- **Stop querying Claude context usage after turns** (pingdotgg#8610) — a cheap
correctness/cost fix in the same place Moatless polls.
- **Server-side accept and size-limit non-image uploads** (pingdotgg#8235), the
other half of the gap above.
- Auto-settling churn (pingdotgg#8321 made it opt-in, pingdotgg#8596 reverted) nets to no
change — noted so the next merge does not re-derive it.

## Verification

`verify.mjs`: `tripwires`, `fmt:check`, `lint`, `typecheck` pass. `test`
reports `@t3tools/web` **flaky, passed alone** — in the full run
`MessagesTimeline.test.tsx` skipped all 34 tests on a 30s module-import
timeout under `ChatMarkdown.tsx`; alone the package is 297 files / 3117
tests green. Load, not the merge. `inventory-check.mjs` clean.

Model: Claude Opus 5, via Claude Code in a Moatless sandbox.

---
Moatless task:
https://moatless.soaplabstest.com/tasks/a0c041bb-1426-4591-9296-6a4b0cfa2eff
juliusmarminge added a commit that referenced this pull request Aug 29, 2026
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: #8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), #5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, #8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, #8481 client
analytics through the v2 ws layer, #8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

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