Found during the integration review of PR #279 (issue #273).
The defect
packages/codev/src/agent-farm/servers/tower-routes.ts:997 handles POST /api/terminals/:id/write with a bare session.write(body.data) and no byte bound.
A tty input queue is finite. On macOS it is 1024 bytes, and a single write larger than the queue can hold is truncated silently: pty.write() returns without error, so every layer above reports success for bytes that never reached the agent. That is exactly what #273 was, measured there as 1024 of 1274 bytes delivered on a single write.
Why it is filed separately
#273 fixed the message path, where writeMessageToSession now segments at MAX_WRITE_CHUNK_CHARS and paces the chunks. This route is the raw keystroke passthrough and was out of that scope. The hazard is identical; only the entry point differs.
What would close this
- Route this write through the same segmentation
message-write.ts now provides, rather than adding a second bound that can drift from the first.
- A test at the write call site with a payload over the cap, verified to fail without the fix.
Related
There is also no message-size cap at ingest anywhere in handleSend or the mailbox, so pacing duration is unbounded: roughly 200 chunks and 2 seconds for 50KB, 20 seconds for 500KB, held under the per-terminal submit lock on the --interrupt path. Worth deciding whether a cap belongs at ingest rather than only at the write.
Source
.consult-runs/integration-273.md, integration review of PR #279.
Found during the integration review of PR #279 (issue #273).
The defect
packages/codev/src/agent-farm/servers/tower-routes.ts:997handlesPOST /api/terminals/:id/writewith a baresession.write(body.data)and no byte bound.A tty input queue is finite. On macOS it is 1024 bytes, and a single write larger than the queue can hold is truncated silently:
pty.write()returns without error, so every layer above reports success for bytes that never reached the agent. That is exactly what #273 was, measured there as 1024 of 1274 bytes delivered on a single write.Why it is filed separately
#273 fixed the message path, where
writeMessageToSessionnow segments atMAX_WRITE_CHUNK_CHARSand paces the chunks. This route is the raw keystroke passthrough and was out of that scope. The hazard is identical; only the entry point differs.What would close this
message-write.tsnow provides, rather than adding a second bound that can drift from the first.Related
There is also no message-size cap at ingest anywhere in
handleSendor the mailbox, so pacing duration is unbounded: roughly 200 chunks and 2 seconds for 50KB, 20 seconds for 500KB, held under the per-terminal submit lock on the--interruptpath. Worth deciding whether a cap belongs at ingest rather than only at the write.Source
.consult-runs/integration-273.md, integration review of PR #279.