Skip to content

stack 3/5: carry six contributor bug fixes with authorship intact - #953

Open
lidge-jun wants to merge 8 commits into
codex/908-long-context-pricingfrom
codex/carry-contributor-bugfixes
Open

stack 3/5: carry six contributor bug fixes with authorship intact#953
lidge-jun wants to merge 8 commits into
codex/908-long-context-pricingfrom
codex/carry-contributor-bugfixes

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Stack

3/3 — carried contributor bug fixes

Base: codex/908-long-context-pricing (#952)

Summary

Carries six contributor bug fixes onto the stack, unmodified, with original authorship preserved via git cherry-pick -x. Every commit keeps its author; git log --format='%an' shows the contributor, not me.

Source PR Author Carried commits Fix
#939 @DevMello 1 keep a marker for tool_result document blocks
#943 @DevMello 1 fail closed on MALFORMED_FUNCTION_CALL without a call part
#944 @DevMello 1 separate reasoning summary parts in streamed thinking
#945 @DevMello 1 report upstream usage for native compact turns
#942 @L14nY1Wang 1 close passthrough streams at terminal events
#948 @mushikingh 3 round-trip the Kiro redactedContent reasoning blob

Eight commits, +604/-70 across 20 files. No content changes were made to any of them — this is a carry, not a rework. Each applied to dev cleanly with no conflict resolution, so what is reviewed here is byte-identical to what the authors wrote.

Why carry rather than merge in place

These are small, focused, independently-correct fixes that were sitting unmerged behind a long review queue. Stacking them puts them on one branch with one CI run and one review pass, in the same bottom-up order as the rest of the stack.

The source PRs stay open until this lands. If a maintainer prefers to take any of them directly instead, that path is unaffected — drop the corresponding commits here and merge the original. Once this merges, each source PR can be closed as carried, with credit already recorded in the commit history rather than in a comment.

Not carried, and why

PR Author Reason
#947 @WZBbiao conflicts with #942's terminal-event handling — both touch the same relay path, and resolving that is the author's call, not a carry
#933 @IMHinnG draft, enforce-target failing
#928, #922, #940, #935 CHANGES_REQUESTED — carrying a PR past requested changes would route around the review

Verification

  • bun x tsc --noEmit — exit 0
  • bun test on all 11 touched test files — 331 pass, 0 fail
  • bun run test — 7691 pass, 8 skip, 0 fail, 507 files
  • bun run privacy:scan — passed

Full-suite green is what matters here: these six fixes touch Claude inbound/outbound, Google streaming, compaction, passthrough terminals, and the Kiro adapter, and nothing in the suite regressed.

DevMello and others added 8 commits August 4, 2026 00:42
A tool_result whose content is a document block translated to an
empty tool output, so routed models treated the attachment as a tool
that returned nothing. Surface the same "[document: title]" marker
the user-message path already emits.

(cherry picked from commit 3cdf190)
Gemini usually drops the malformed call upstream, so the final chunk
carries only the finishReason and the started-calls guard never fired.
The turn surfaced as a clean empty completion instead of an error.
MAX_TOKENS with no started call keeps its plain token-limit stop.

(cherry picked from commit 6eb5903)
The streaming translator folded every summary part into one thinking
block with no separator, so multi-part summaries rendered as run-on
text. The JSON path already joins parts with a blank line; the stream
now emits the same separator at part boundaries.

(cherry picked from commit b23cc1f)
The native branch buffers the upstream compact JSON and returns it
without inspecting the body, so the request log row lands with no
usage. Lift usage and response metadata from the buffered body the
same way the routed branch gets it through handleResponses.

(cherry picked from commit 2ae3b5f)
Kiro never returns plaintext reasoning for its Sol-family models. Its
`reasoningContentEvent` carries a KMS-encrypted `redactedContent` blob, and
`gpt-5.6-sol`'s `additionalModelRequestFieldsSchema` accepts only
`reasoning.effort` — there is no display or summary opt-in. Kiro's own CLI
replays that blob on the matching `assistantResponseMessage.reasoningContent`
to preserve model reasoning across turns.

The adapter read only `reasoningContentEvent.text`, which is absent on this
wire, so the blob was dropped and never replayed. Every turn therefore
restarted without the previous turn's reasoning.

- kiro-events: parse `redactedContent`; add the previously unhandled
  `contextUsageEvent` (Kiro reports context pressure there, not in
  `metadataEvent`, which carries only `stopReason`).
- Carry the blob through the existing `ocxr1:` envelope as `krc` on an
  envelope-only reasoning item, so it round-trips while staying invisible in
  the app — the same contract the hidden-thinking path already uses.
- Pair it backwards: Kiro emits the event at the END of a turn, after content
  and tool calls, so a krc-only item belongs to the assistant turn that already
  closed. Folding it forward would attach turn N's blob to turn N+1. With no
  assistant turn to own it, the blob is dropped rather than mis-paired.
- Replay it on `assistantResponseMessage.reasoningContent`.

Verified against kiro-cli 2.14.1 and 2.16.0 request/response captures.

(cherry picked from commit cbb5d21)
CodeRabbit caught a real defect that made the round-trip a no-op in the
streaming path.

Kiro sends its reasoning blob at the END of a turn, while the assistant message
is still open. Emitting the envelope-only item on arrival was wrong twice over:

- `outputIndex` only advances when an item CLOSES, so the open message and the
  envelope item were emitted under the same output index.
- The envelope landed BEFORE the assistant message, and the parser pairs a
  krc-only item backwards, so it found no preceding assistant turn and dropped
  the blob as orphaned — silently defeating the fix.

Both paths now stash the blob and flush it after every open item has closed:
after the closes in the streaming `done` case, and after the trailing flushes in
the batch path. Message phase inference is untouched, so a Kiro final answer is
still classified `final_answer` rather than being force-closed as commentary.

The batch path also released `bytesOf(encrypted)` through `pushOutput` without
ever retaining it. It now charges the blob when stashing and lets `pushOutput`
release that retained allocation, so the translator budget balances.

Adds tests/kiro-reasoning-roundtrip.test.ts, which bridges adapter events and
re-parses the emitted items the way Codex replays history — the end-to-end
coverage the original tests lacked. Three of its five cases fail against the
previous commit.

Scope: verified that gpt-5.6-terra and gpt-5.6-luna return `redactedContent`
exactly like gpt-5.6-sol, so the whole GPT-5.6 family was affected. Handling
keys off the wire field, not the model id.

(cherry picked from commit bd13d48)
…blob

The batch budget assertion was vacuous twice over. It passed the budget in the
wrong argument position, so `buildResponseJSON` built its own internal budget and
the snapshot under test was never written to (`highWaterBytes: 0`). Even wired
correctly, asserting `currentBytes >= 0` could not distinguish a leaked raw blob
from the finalized items that legitimately stay retained.

It now uses a 4 KB blob and asserts `currentBytes` equals EXACTLY the finalized
output items' bytes — a still-retained raw blob shows up as ~4 KB of excess, and
releasing bytes that were never charged shows up as a shortfall. A separate
`highWaterBytes` assertion proves the blob was charged while held rather than
never accounted for. Four of the file's five cases now fail against cbb5d21.

Also corrects the metadataEvent description: every capture put the context
percentage in `contextUsageEvent`, but the parser still accepts a finite
`contextUsagePercentage` (and `tokenUsage`) from `metadataEvent` as a fallback,
so documenting it as impossible was wrong.

(cherry picked from commit 8610630)
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e1a1a269-07c9-45b1-9ab9-c856d81abc34

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.

@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, and the carried contributors' paths — so any layer can be retargeted to dev and taken independently without a rebase conflict if you prefer.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9664abdd18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const clientBody = process.platform === "win32" && !needsClientRewrite
? nativeBody
: relaySseWithFailedTail(rewrittenBody, upstream, reason => clientGone.abort(reason));
const clientBody = relaySseWithFailedTail(rewrittenBody, upstream, reason => clientGone.abort(reason));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the native Windows tee client path

On Windows with the default streamMode: "auto" or explicit legacy-tee, no-rewrite traffic does not enter the eager branch because MIN_FIXED_BUN_VERSION is still null; it therefore reaches this unconditional relaySseWithFailedTail JS pull wrapper. This recreates the Bun#32111 path that the removed nativeBody branch avoided, so the bundled known-bad runtime can crash or lose terminal frames. Keep the native client branch for Windows decisions where useEagerRelay is false, or only use a JS relay once the runtime is proven fixed.

AGENTS.md reference: AGENTS.md:L206-L208

Useful? React with 👍 / 👎.

Comment thread src/server/relay.ts
return {
feed(chunk) {
if (disposed || terminal) return new Uint8Array(0);
buffer += decoder!.decode(chunk, { stream: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bound incomplete frames in the terminal relay

When an upstream sends a very large or never-terminated SSE event, every chunk is appended to buffer until a blank-line delimiter arrives, with no byte cap or timeout. This new boundary is now on passthrough response paths, so a stuck or hostile compatible gateway can grow proxy memory without limit and withhold all of that event from the client. Apply a bounded frame policy and fail closed or safely fall back when the cap is exceeded.

AGENTS.md reference: src/AGENTS.md:L17-L17

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)
  4. stack 4/5: keep an explicit thinking disable through translation (#545) #954 — Claude Desktop classifier thinking round-trip, Claude Desktop 3P Auto Mode classifier retries after 64-token Anthropic OAuth outputs #545 (base stack 3/5: carry six contributor bug fixes with authorship intact #953)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, the carried contributors' paths, and src/claude/ + src/adapters/anthropic.ts — so any layer can be retargeted to dev and taken independently without a rebase conflict.

#954 needs human security review per MAINTAINERS.md: it changes request construction on an Anthropic OAuth execution path. It is last in the stack so the first three can land without waiting on that.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@lidge-jun lidge-jun changed the title stack 3/3: carry six contributor bug fixes with authorship intact stack 3/4: carry six contributor bug fixes with authorship intact Aug 3, 2026
@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)
  4. stack 4/5: keep an explicit thinking disable through translation (#545) #954 — Claude Desktop classifier thinking round-trip, Claude Desktop 3P Auto Mode classifier retries after 64-token Anthropic OAuth outputs #545 (base stack 3/5: carry six contributor bug fixes with authorship intact #953)
  5. stack 5/5: probe reset-derived cooldowns without waiting to be selected (#915) #955 — cooldown early-recovery probe, [Bug]: Reset-derived cooldowns can miss early recovery while another pool account remains eligible #915 (base stack 4/5: keep an explicit thinking disable through translation (#545) #954)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, the carried contributors' paths, src/claude/ + src/adapters/anthropic.ts, and src/codex/ — so any layer can be retargeted to dev and taken independently without a rebase conflict.

#954 needs human security review per MAINTAINERS.md: it changes request construction on an Anthropic OAuth execution path. #955 sits above it in the chain but is independent of it in code, so if that review blocks, #955 can be retargeted to #953 without conflict.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@lidge-jun lidge-jun changed the title stack 3/4: carry six contributor bug fixes with authorship intact stack 3/5: carry six contributor bug fixes with authorship intact Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants