Skip to content

fix(responses): refuse oversized input and stop compounding replayed history - #1412

Draft
HoshimiRox1 wants to merge 2 commits into
lidge-jun:devfrom
HoshimiRox1:fix(codex)/responses-input-guard-compaction
Draft

fix(responses): refuse oversized input and stop compounding replayed history#1412
HoshimiRox1 wants to merge 2 commits into
lidge-jun:devfrom
HoshimiRox1:fix(codex)/responses-input-guard-compaction

Conversation

@HoshimiRox1

@HoshimiRox1 HoshimiRox1 commented Aug 10, 2026

Copy link
Copy Markdown

Summary

Two fixes for the Codex desktop context/compaction failure chain (reported upstream in #1128).

  • refuse responses input beyond the advertised context window — a chained-turn replay can balloon a request far past the model's context window. Forwarding it on Windows ballooned bun RSS and native-crashed the whole proxy service (upstream Bun memory bug, 램 누수가 있어요 #314), taking every active thread down until restart. The proxy now rejects such requests with a clean 413 before any upstream I/O.
  • stop compounding replayed history on already-full requestsexpandPreviousResponseInput prepended the stored history unconditionally. Stateless upstreams (DeepSeek documents "every turn must resend the full history") make the client carry the full conversation in input while still chaining with previous_response_id; prepending then duplicates it, and recording the duplicated body makes the bloat sticky: 1x → 2x → 3x → … The expansion now detects the overlap via canonical item keys (ignoring volatile ids/status) plus an item-count rule, keeps the request's own input when it already begins with the stored history, and still expands genuine delta continuations.

Context and reproduction evidence

The trigger is the continuation turn right after a tool result: the client resends the full conversation plus previous_response_id, and the old expansion prepended the stored copy again. This is not web-search-specific — shell results, hosted search results, and any other tool-result round-trip share the same shape. Web-search/tool loops are the high-frequency scenario because they produce many consecutive tool-result continuations.

Live observations (stock 2.11.1, all requests returned 200):

  • 2026-08-10 23:54:14, conversation c527a04a: input 239,957485,943 (~2.0x), then back to 252,901 on the next request. 23:59:28, another conversation: 565,484.
  • 2026-08-10 09:26:20, same thread: 1,333,682 (cached 1,325,824, ~99.4% cache hit) while the real conversation was ~127k tokens; the session log shows a compacted event immediately after.
  • 2026-08-06 18:44:30: 1,609,389 (cached 1,604,224), immediately after a shell_command result (GitHub API check), followed by compaction failure (stream closed before response.completed) and a proxy crash.
  • Reconstruction from the archived real thread: before the fix the same real items expanded 2x → 3x → 4x; after the fix every full turn stays 1x.

Verification

  • bun test tests/responses-replay-overlap.test.ts tests/responses-input-guard.test.ts — 7 pass, 0 fail (full-history chained turns stay 1x; delta turns still expand; stateless DeepSeek end-to-end keeps upstream at 1x).
  • Related suites: 227 pass / 4 fail — the 4 failures are the pre-existing Windows symlink EPERM sandbox cases in responses-state.test.ts, unrelated to this change.
  • bun run typecheck — pass.
  • bun run privacy:scan — pass.
  • git diff --check — pass.
  • Patched install live check: the same reproduction steps that produced 2x spikes on stock keep upstream at 1x.
  • Full bun run test was attempted earlier on Windows: unrelated codex-journal restoration tests remained red in isolation and the run ended in a Bun 1.3.14 index-out-of-bounds crash. Focused and related suites stay green, so this PR remains draft for CI confirmation.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed. No user-facing configuration or API contract changed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. No credential or logging path changed.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate conversation history when chained responses resend previously included items.
    • Improved replay handling for partial overlaps, repeated items, and reordered content.
    • Preserved complete request history when already included in a follow-up request.
  • Request Handling

    • Added protection against inputs exceeding the configured model context window.
    • Oversized requests now return a clear 413 request_too_large error before processing.
    • Requests within the model’s context limit continue normally.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c27a5c3b-b15f-4bc4-b5d1-3020ee284c09

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5768c and 4e3c4ff.

📒 Files selected for processing (1)
  • src/responses/state.ts

📝 Walkthrough

Walkthrough

The change adds canonical overlap detection for chained response history and a pre-forwarding context-window guard. Full-history requests avoid duplicate items, delta requests retain stored history, and oversized inputs return HTTP 413.

Changes

Response replay overlap

Layer / File(s) Summary
Replay overlap expansion
src/responses/state.ts
Canonical item comparison ignores volatile fields and property order. Chained input preserves complete-overlap requests and prepends stored history for delta requests.
Replay continuation validation
tests/responses-replay-overlap.test.ts
Tests cover full-history replay, delta expansion, canonical matching, partial overlap, stateless DeepSeek requests, and upstream item counts.

Responses input context guard

Layer / File(s) Summary
Context-window enforcement
src/server/responses/core.ts
The handler estimates tokens from message strings and text parts. It returns HTTP 413 with input_context_window_exceeded before forwarding oversized input.
Context-window guard validation
tests/responses-input-guard.test.ts
Tests verify rejection of oversized input without an upstream call and forwarding of input within the configured window.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant handleResponses
  participant expandPreviousResponseInput
  participant Upstream
  Client->>handleResponses: Submit chained response request
  handleResponses->>expandPreviousResponseInput: Provide previous_response_id and input
  expandPreviousResponseInput->>expandPreviousResponseInput: Compare canonical replay prefix
  expandPreviousResponseInput-->>handleResponses: Preserve full history or prepend stored history
  handleResponses->>Upstream: Forward expanded input
Loading

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes both primary changes: rejecting oversized Responses input and preventing repeated replayed history.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 10, 2026
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (1/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 1/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

1/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@HoshimiRox1 HoshimiRox1 changed the title fix(responses): refuse input beyond the advertised context window (#1128) fix(responses): refuse oversized input and stop compounding replayed history (#1128) Aug 10, 2026
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 1598a96 to 1bab097 Compare August 10, 2026 15:18
A chained-turn replay can balloon a request far past the model's context window (observed: a 4x expansion pushed a ~400k-token conversation to 1.6M input tokens). The proxy forwarded it verbatim; processing it on Windows ballooned bun RSS and native-crashed the whole service (upstream Bun memory bug, lidge-jun#314), taking every active thread down until restart.

Reject the request with a clean 413 before any upstream I/O when the parsed input exceeds the model's configured modelContextWindows value. The client compacts well before the window, so the guard only fires on abnormal duplication.
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 1bab097 to 67379fd Compare August 11, 2026 01:50
@HoshimiRox1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/responses/state.ts`:
- Around line 732-735: Update canonicalReplayItemKey in src/responses/state.ts
(lines 732-735) to recursively sort retained object keys, including nested
objects, before serialization so equivalent items produce identical canonical
keys; preserve the existing excluded fields. Add a regression case in
tests/responses-replay-overlap.test.ts (lines 118-133) using stored and resent
items with different retained key order, and assert they overlap without
duplicating history.
- Around line 886-898: Update the replay merge logic in replayedPrefixOverlap
handling within src/responses/state.ts lines 886-898 to preserve request
unchanged only for complete overlap; otherwise append
requestItems.slice(overlap) after storedItems, avoiding duplicated matched
prefixes and omitted stored items. Add a regression test in
tests/responses-replay-overlap.test.ts lines 100-116 covering a partial prefix
plus delta and asserting each history item appears exactly once.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c9d3db0b-6cee-4313-9fba-da97765c85e4

📥 Commits

Reviewing files that changed from the base of the PR and between 8ab41d3 and 67379fd.

📒 Files selected for processing (4)
  • src/responses/state.ts
  • src/server/responses/core.ts
  • tests/responses-input-guard.test.ts
  • tests/responses-replay-overlap.test.ts

Comment thread src/responses/state.ts Outdated
Comment thread src/responses/state.ts
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 67379fd to 9994bea Compare August 11, 2026 02:05
@HoshimiRox1 HoshimiRox1 changed the title fix(responses): refuse oversized input and stop compounding replayed history (#1128) fix(responses): refuse oversized input and stop compounding replayed history Aug 11, 2026
@HoshimiRox1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/responses/state.ts`:
- Around line 909-913: In src/responses/state.ts lines 909-913, update the
full-history classification in the replay handling around replayedPrefixOverlap
to require complete canonical stored-prefix overlap, removing the
requestItems.length-only condition; any compatibility fallback must validate
item identity rather than count. In tests/responses-replay-overlap.test.ts lines
101-117, add coverage for a delta continuation whose request length is at least
the stored-history length and assert upstream input contains the stored history
followed by every delta item.

In `@tests/responses-replay-overlap.test.ts`:
- Around line 186-201: Set statelessResponses to true in
statelessDeepseekConfig() so postResponses() routes these fixtures through the
stateless adapter branch when passed directly to handleResponses().
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b5826d00-4332-4961-b9e0-b2c493671195

📥 Commits

Reviewing files that changed from the base of the PR and between 67379fd and 9994bea.

📒 Files selected for processing (2)
  • src/responses/state.ts
  • tests/responses-replay-overlap.test.ts

Comment thread src/responses/state.ts
Comment thread tests/responses-replay-overlap.test.ts
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 9994bea to 562c553 Compare August 11, 2026 02:19
@HoshimiRox1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/responses/state.ts`:
- Around line 753-758: Update replayedPrefixOverlap to canonicalize stored[n]
and requestInput[n] inside the comparison loop instead of mapping both arrays
upfront. Return the accumulated prefix length immediately when either canonical
key is undefined or the keys differ, while preserving the existing
matching-prefix result.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2c01cb42-49cb-4d5b-8774-76de7efce0f6

📥 Commits

Reviewing files that changed from the base of the PR and between 9994bea and 562c553.

📒 Files selected for processing (2)
  • src/responses/state.ts
  • tests/responses-replay-overlap.test.ts

Comment thread src/responses/state.ts
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 562c553 to 3e5768c Compare August 11, 2026 02:24
@HoshimiRox1
HoshimiRox1 marked this pull request as ready for review August 11, 2026 02:32
@github-actions
github-actions Bot marked this pull request as draft August 11, 2026 02:32

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/responses/state.ts`:
- Around line 735-738: Update the canonicalization block in canonicalReplayValue
to create out with a null prototype instead of a normal object, preserving any
own JSON __proto__ key as a serializable property while leaving the sorted-key
traversal and recursive canonicalization unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a5014d0b-b026-40ee-8f78-30b7c9f5db34

📥 Commits

Reviewing files that changed from the base of the PR and between 562c553 and 3e5768c.

📒 Files selected for processing (1)
  • src/responses/state.ts

Comment thread src/responses/state.ts Outdated
A chained /v1/responses turn may carry the full conversation (stateless upstreams such as DeepSeek force the client to resend it every turn). expandPreviousResponseInput prepended the stored history unconditionally, so a full-body request duplicated it, and recording the duplicated body made the bloat sticky across turns: 1x -> 2x -> 3x -> ... (observed 1,333,682 input tokens on 2026-08-10, ~10x the real ~127k conversation). Detect the overlap via canonical item keys (ignoring volatile ids/status) plus an item-count rule, keep the request's own input when it already begins with the stored history, and only prepend for genuine delta continuations.
@HoshimiRox1
HoshimiRox1 force-pushed the fix(codex)/responses-input-guard-compaction branch from 3e5768c to 4e3c4ff Compare August 11, 2026 02:36
@HoshimiRox1

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant