Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Feature: opt-in per-provider request byte budget that downscales then prunes inline images

Closed
#2,511 3 comments 0 reactions 0 assignees View on GitHub

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
Domain
api, backend

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

enhancement priority: P3 provider proxy
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:

  1. Codex sends images at original resolution. A Retina screenshot is 2–4 MB of base64. There is no client-side byte budget.
  2. OpenCodex replays the full history. expandPreviousResponseInput (src/responses/state.ts) materializes the stored previous_response_id state back into input, so every turn re-sends every image ever attached. This is correct for cross-provider routing, but it means the payload only grows.
  3. 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:

  1. Downscale oversized inline images (re-encode to a bounded longest-edge JPEG). Cheap, lossy only in resolution, keeps every image present.
  2. Prune oldest-first if still over budget: replace the oldest input_image parts with an explicit input_text marker (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_id continuation 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.
  • /compact requires 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 maxRequestBytes seems 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lidge-jun/opencodex

All issues in lidge-jun/opencodex

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.