fix(rpc): send commands to omp as single unchunked lines (#105) - #107
Merged
Merged
Conversation
Protocol-v2 `rpc_chunk` framing is an outbound encoding only. omp parses one JSONL object per stdin line and never runs the chunk decoder, so every command above 1 MiB — any prompt carrying a photo, clipboard screenshot, or similar attachment — was answered `Unknown command: rpc_chunk` under an id it could not correlate. The prompt then sat until the 30s ack timeout killed the child and reported `session_unresponsive`. `encodeRpcCommand` always emits one record, however large, with a 32 MiB bound so a pathological command fails fast with a clear error instead of hanging. Reproduced against a real `omp --mode rpc-ui`: the old framing produced five `Unknown command: rpc_chunk` responses for a 1.2 MB `switch_session`, the new framing is parsed and correlated normally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #105.
Attaching a normal photo or clipboard screenshot reset the session with "The OMP session stopped responding and was reset." Root cause is exactly as reported:
RpcProcess.writeFrameranencodeRpcFrameson every stdin command, so once protocol v2 was negotiated any command overMAX_RPC_FRAME_BYTES(1 MiB) was split intorpc_chunkrecords. OMP's stdin reader parses one JSONL object per line and never runs the chunk decoder, so each record was rejected:{"type":"response","command":"rpc_chunk","success":false,"error":"Unknown command: rpc_chunk"}with no
idto correlate. The prompt never acked, and afterPROMPT_ACK_TIMEOUT_MSthe healthy child was killed and reported assession_unresponsive.Protocol-v2 chunking is an outbound encoding (omp → host); the advertised
maxFrameBytesbounds omp's physical frames, not the host's commands.Change
lib/omp/rpc-frame.ts:encodeRpcFrames(frame, protocolVersion, chunkId)→encodeRpcCommand(frame), which always returns a single unchunked JSONL record however large. AddedMAX_INBOUND_COMMAND_BYTES(32 MiB) so a pathological command fails fast with a clear error (RPC command exceeds the …-byte inbound transport limit) instead of an unbounded pipe write.RpcFrameDecoderis unchanged — omp's oversized outbound frames are still reassembled.lib/omp/rpc-process.ts:writeFramewrites one line, chunk-id bookkeeping removed, doc comments updated. Commands stay serialized through the FIFO queue so they cannot interleave and a failed write cannot reorder pending responses.The composer/route preflight the issue asks for already exists (
validateOutgoingPromptincomponents/ChatInput.tsx,parseJsonWithinLimit(req, MAX_AGENT_COMMAND_REQUEST_BYTES)in both agent routes), so messages over 8 MiB are rejected before send, and a serialization failure now surfaces immediately rather than as a session reset.Verification
Reproduced against a real
omp/18.1.19child (omp --mode rpc-ui, protocol v2 negotiated), sending the same 1.2 MB logical command both ways:The oversized command is now parsed and correlated by its own id (the error is just the bogus path used as a payload), so the prompt can no longer wedge.
Tests:
lib/omp/rpc-frame.test.mjs: oversized command stays one record (and never containsrpc_chunk); over-cap command throws before any write; unchunked command still decodes; decoder still reassembles and still rejects reordered/mismatched chunk sequences.lib/omp/rpc-process-runtime.test.mjs: new regression test — after v2 negotiation a ~2 MiBpromptis written as one stdin line, acks, and produces norpc_chunkcommand.npm test— 800 pass / 0 fail / 5 skipped (full suite),tsc --noEmitclean,eslintclean.