Skip to content

perf(ai): streaming requests stop pinning a full clone of their wire payload - #899

Open
santhreal wants to merge 6 commits into
mainfrom
perf/provider-dump-retention
Open

perf(ai): streaming requests stop pinning a full clone of their wire payload#899
santhreal wants to merge 6 commits into
mainfrom
perf/provider-dump-retention

Conversation

@santhreal

Copy link
Copy Markdown
Owner

What

Three changes to how in-flight provider requests hold memory:

  1. openai-completions, openai-responses, azure-openai-responses: the diagnostic rawRequestDump.body held the parsed request object from the moment the request left until the stream ended — so a large context stayed resident twice for the life of every request (the live context plus the dump's clone). The dump now retains only the exact sent bytes (wireBodyJson), and a new materializeDumpBody helper parses those bytes back into body at error time, when a 400/413 dump is actually built. Bytes that never sent or never parse leave body unset rather than fabricating one.

  2. pi-native-client: serialized its full body once for the payload hook and again for fetch. It now serializes once, hands the hook an isolated parse of those bytes, and reuses them on the wire when the hook leaves the payload alone. The hook-rejection wrapping in PiNativePayloadHookError is preserved.

  3. The reasoning-effort fallback retry paths no longer eagerly copy params into the dump; the retried attempt's own serialization records them.

Why

For a session carrying a multi-megabyte context, every concurrent stream — including side streams and advisors — kept an entire context-sized object graph alive doing nothing. This was pure diagnostic insurance that almost never pays out (only 400/413 dumps read it).

Testing

  • New unit tests for materializeDumpBody (packages/ai/test/http-inspector.test.ts): parses retained bytes, leaves body-less dumps untouched when nothing was sent, never clobbers an existing body, tolerates unparseable/truncated bytes.
  • Full affected provider suites green in the sandbox: azure-openai-responses-stream (14 tests), openai-completions-compat, openai-responses-stream, pi-native-client, http-inspector — 121 pass / 0 fail; full packages/ai suite run shows no new failures.
  • Existing onPayload contract tests (hook isolation across retries, replacement bodies) pass unchanged.
  • bun run check:ts, bun run check:tools clean.

Memory effect

Per in-flight stream: peak retention drops by one full serialized-context object graph (typically ~2–4× the JSON byte size) for openai-completions / responses / azure responses requests, and by one whole-body JSON string + parse cycle per attempt on pi-native.


  • bun check passes
  • Tested locally
  • CHANGELOG updated (if user-facing)

openai-completions, openai-responses and azure-openai-responses kept
the parsed request object in the diagnostic dump from the moment
headers left until the stream ended, so a large context stayed
resident twice for the life of every request. The dump now retains
only the exact sent bytes and materializes its body through the new
materializeDumpBody helper when a 400/413 dump is actually built.

The pi-native client serializes its body once and hands the payload
hook an isolated parse of those bytes, reusing them on the wire when
the hook leaves the payload alone instead of serializing the full
context a second time.
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 80fa5cee-88b3-4d19-a05c-df3d4e293387


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.

The completions-family request builders deep-cloned the whole params
graph per attempt just to give the payload hook an isolated object,
then serialized the result: on a 32MiB context that is 82ms of
clone-plus-stringify against 9ms for serialize-once, paid on every
submit before the first byte. The hook now gets an isolated parse of
the single serialization, an untouched payload reuses those bytes on
the wire, and only a genuinely replaced payload costs a second pass.
VEYYON_DEBUG_STARTUP=1 now writes one synchronous stderr line per
submit phase — compaction check, plan arm, context build, memory
context, before_agent_start, pre-prompt compaction — so a 'submit feels
slow' report names the phase that spent the time instead of offering a
guess.
…object

Anthropic, Google Generative AI/Vertex, Gemini CLI, Bedrock, Ollama and
Codex kept their parsed request object in rawRequestDump for the whole
stream; they now record the exact sent bytes and materialize the dump
body through materializeDumpBody when a 400/413 dump is built.
The codex websocket/SSE prepare path deep-cloned the whole request
graph per attempt for payload-hook isolation. Serialize-once with an
isolated parse replaces it: untouched payloads reuse the recorded
bytes on the wire, replaced ones pay a second pass.
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.

1 participant