mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 02:00:52 +01:00
Round 4 of the bridge body admission fix. reserveBodyRead and readBody took a flat maxBodyBytes charge for every active read. That charge was too large for a small control-plane call and too small for the file gateway, whose real retained peak reaches several times the raw body size once it decodes, re-serializes, and re-encodes the body. Read the Content-Length header before the gateway reserves anything. Reject a body that declares more than the cap with a clean 413, before the gateway reserves or reads one byte. When the header is absent (a chunked request), fall back to the cap as the worst case, the same as before. Charge the reserve and the read buffer from the declared length times a named per-gateway factor: - The duplex gateway adds a fixed frame allowance to the declared length, because it holds one body buffer plus at most one in-flight frame that does not grow with the body. - The file gateway multiplies the declared length by a factor of 15, the sum of the four representations it holds: the raw buffer, the decoded string, the JSON-escaped string, and the write buffer. The comment on the constant names each one and its worst-case size. Fix the outbound stdout writer so a stream error settles every queued write, not only the one at the head of the queue. The old top-of-loop check discarded queued entries with no reject call, and the resume path after a stalled write could remove and orphan a line a caller queued after the stream had already failed. Both left a promise that never settled, which stalled the reserve release and shed every later request until the process restarted. Add unit tests for the writer fix and end-to-end tests on both gateways for the declared-length admission model: the pre-reserve 413, the worst-case fallback for a request with no declared length, many small concurrent requests the old flat charge would have shed, and the admission-bound math at the new per-gateway reserve. Co-authored-by: Paperclip <noreply@paperclip.ing> Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>