Feature: opt-in per-provider request byte budget that downscales then prunes inline images
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 50/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- typescript
Research direction
Start with src/responses/state.ts and trace the responses request-building and provider-configuration entry points that feed it. Verify where the full payload is materialized and compactly serialized, including nested tool outputs. Done means an opt-in budget can reduce oversized requests while preserving newest images, handling nested images, and leaving default behavior unchanged.
Written by the indexing model from the issue text.
Description
Area
Proxy and routing
What are you trying to accomplish?
I want image-heavy Codex sessions to survive against providers whose gateway enforces a hard request-body size limit, instead of the thread becoming permanently unusable.
Concretely: I attach screenshots and let Codex read rendered PDF/PPT pages while working. After enough images accumulate in the thread, every subsequent turn fails with a provider-side body-size rejection, and the thread can never recover — including its own compaction attempt, because that request also carries the history.
What prevents this today?
Three things combine:
- Codex sends images at original resolution. A Retina screenshot is 2–4 MB of base64. There is no client-side byte budget.
- OpenCodex replays the full history.
expandPreviousResponseInput(src/responses/state.ts) materializes the storedprevious_response_idstate back intoinput, so every turn re-sends every image ever attached. This is correct for cross-provider routing, but it means the payload only grows. - Codex auto-compaction cannot save the thread. Compaction triggers on tokens, while the gateway limit is bytes. Images are byte-heavy and token-light (a 1 MB screenshot is ~1.4 MB base64 but only ~1–2.5k vision tokens), so the byte ceiling is reached long before the token threshold. Nothing in the pipeline watches serialized body size.
Measured limits on Alibaba Cloud Bailian (Model Studio), OpenAI-compatible endpoints:
| Endpoint | Body cap | Error |
|---|---|---|
public dashscope.aliyuncs.com/compatible-mode/v1 |
6 MB | BadRequest.TooLarge: Exceeded limit on max bytes to request body : 6291456 |
dedicated Bailian host (*.maas.aliyuncs.com) |
10 MB | RequestEntityTooLarge: Request body size exceeds maximum allowed size: 10485760 bytes |
Bailian's Responses API also has no files/file-id upload mechanism, and its input_image field is documented as taking a public URL — but Codex only produces inline base64, so that escape hatch is unavailable.
What should OpenCodex do?
Add an opt-in, per-provider request byte budget in the responses pipeline. When the serialized body exceeds the budget, slim it in two ordered passes before forwarding:
- Downscale oversized inline images (re-encode to a bounded longest-edge JPEG). Cheap, lossy only in resolution, keeps every image present.
- Prune oldest-first if still over budget: replace the oldest
input_imageparts with an explicitinput_textmarker (e.g.[image removed: request size limit]) so both the model and the user know the image was dropped rather than silently ignored. The newest turn's images survive longest.
Requirements that matter for correctness:
- Must walk the whole payload, not just
input[].content[]— Codex also embeds images inside tool-output items (function_call_output). Scanning only the obvious path silently no-ops. - Must serialize compactly when measuring; a pretty-printed re-serialization can make the body larger.
- Disabled by default, so providers with generous limits are unaffected.
Example usage or interface
// ~/.opencodex/config.json
{
"providers": {
"bailian": {
"adapter": "openai-responses",
"maxRequestBytes": 9000000, // unset = today's behaviour (no slimming)
"imageDownscaleMaxEdge": 1600 // optional; omit to skip pass 1
}
}
}
Log line when it engages:
[opencodex] slimmed body 38729496 -> 5887546 bytes (downscaled=2, pruned=0)
Alternatives or workarounds
I ran a ~230-line stdlib-only local proxy implementing exactly this design in front of Bailian, to check the approach holds end to end:
- Synthetic 38.7 MB two-image request → slimmed to 5.9 MB → upstream 200 with a normal completion. The identical body sent directly upstream returns 413.
- Real Codex turn viewing four 2400×2400 images (66 MB on disk) → completed normally, no error.
- Regressions checked: plain-text turn fine, SSE streaming still incremental,
previous_response_idcontinuation intact.
Workarounds that do not work:
- Switching endpoints only trades 10 MB for 6 MB; the cap is a gateway property, not a wire-format one.
- Instructing the agent (via
AGENTS.md) to downscale before viewing helps but is best-effort, and cannot cover images the user pastes directly. /compactrequires a successful model call, which is exactly what is failing.
Additional context
- This re-files #987, which was auto-closed by the template bot because I opened it via the API without a template. Same proposal, no prior maintainer response.
- Related upstream shape: other OpenAI-compatible gateways (DeepSeek, Moonshot) have comparable body caps, so a generic
maxRequestBytesseems more useful than a Bailian-specific branch. - I am happy to open a PR if the design and config surface look acceptable.
Checks
- I searched existing issues and documentation.
- This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
- I removed secrets and personal data.
- Dominant language
- TypeScript
- Stars
- 16.9k
- Forks
- 1.3k
- Avg merge
- 9h 39m
- Merged PRs (30d)
- 633
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lidge-jun/opencodex
-
bug streaming
lidge-jun/opencodex#7720 · 2 comments ·
Maintainers usually reply within 1 day
-
bug gui platform
lidge-jun/opencodex#7716 · 1 comment ·
Maintainers usually reply within 1 day
-
account-pool provider provider-compatibility
Maintainers usually reply within 1 day
-
catalog enhancement
lidge-jun/opencodex#7705 · 1 comment ·
Maintainers usually reply within 1 day
-
catalog enhancement
lidge-jun/opencodex#7704 · 1 comment ·
Maintainers usually reply within 1 day
All issues in lidge-jun/opencodex
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
cline/cline#15327 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
LogicLabs-OU/OpenArchiver#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
bigcapitalhq/bigcapital#1545 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
Maintainers usually reply within 1 day