Files
PaperClipAI/packages
Nicky LeachandPaperclip 29d12045f4 perf(gateway): remove the whole-body string round trip on the HTTP/2 send path (#12189)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Sandbox agents send callback requests through a generated gateway.
> - The HTTP/2 callback path converts each full request body to a UTF-8
string.
> - The same path converts that string back to a buffer before it sends
the request.
> - This pull request sends the body buffer directly to the HTTP/2
forwarder.
> - The benefit is less copying and unchanged queue payload behavior.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The sandbox callback gateway HTTP/2 send path copies the full request
body through a UTF-8 string before it sends the body.

**Subsystem affected**

The affected subsystem is `packages/adapter-utils`, which contains
sandbox gateway and HTTP/2 adapter utilities.

**Current behavior**

The gateway reads the body into a buffer, converts the complete body to
a UTF-8 string, and converts that string back to a buffer for the HTTP/2
path. The queue path stores the string payload.

**Proposed behavior**

The gateway keeps a byte reader for the HTTP/2 path. A thin text wrapper
keeps the queue path behavior. The HTTP/2 path sends the original body
buffer.

**Reason and benefit**

The extra conversions add work and memory use without changing the
HTTP/2 body bytes. Direct buffer forwarding removes that work and
preserves the size limit and reject behavior.

**Breaking changes**

None. The queue payload remains a string. The body size limit, content
type check, and reject point remain unchanged.

**Additional context**

This change has no public issue link. The repository roadmap search
found no duplicate planned work. The implementation also adds tests for
non-ASCII JSON, malformed UTF-8, size limits, and queue payload shape.

## What Changed

- Add `readBodyBytes(req)` for byte-preserving body reads.
- Keep `readBody(req)` as a string wrapper for the queue path.
- Send the byte buffer directly on the HTTP/2 path.
- Add tests for byte identity, malformed UTF-8, size limits, and queue
payload shape.

## Verification

- `pnpm --filter @paperclip/adapter-utils test
src/sandbox-callback-bridge.test.ts` passed with 51 tests.
- `pnpm --filter @paperclip/adapter-utils exec tsc --noEmit` passed.
- The tests spawn the generated gateway and the real host HTTP/2 bridge.
- The tests verify byte identity, malformed UTF-8, pre-forward size
rejection, queue file protection, and string queue payloads.
- Full repository CI must pass before merge.

## Risks

Low risk. The HTTP/2 path changes its internal body conversion only. The
queue path keeps the prior string payload. The size limit and reject
point stay unchanged.

## Model Used

OpenAI Codex, GPT-5, tool use and code review assistance. The exact
runtime context window is managed by the Codex service.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-25 14:56:17 -07:00
..