Submit sent input into agent TUIs instead of their composer - #1190
Merged
Conversation
`construct send` and the MCP input tool both arrive as the SESSION_INPUT IPC method, which called `send_input`. That writes the text LF-terminated, and LF is not the byte a terminal's Enter key sends — in a crossterm TUI in raw mode it is Ctrl+J, "insert a newline". Against codex the message landed in the composer and sat there unsubmitted, so the send looked like a silent no-op: the caller got an Ok, the text was visible in the pane, and no turn ever started. The daemon already knows the framing each harness submits on, and the service ingress path was fixed to use it. Route the dispatch through `deliver_user_text` too, so PTY-backed agent TUIs get bracketed paste plus Enter, PTY line editors get CR, and headless harnesses keep going through `send_input` unchanged. The regression is invisible from the caller's side, so the test drives a real SESSION_INPUT request through `dispatch` rather than asserting against the manager helper it happens to delegate to today; it fails against the old wiring. `dispatch` and `SubCmd` become `pub(crate)` to let the test reach that entry point.
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.
Problem
construct sendand the MCP input tool both arrive as theSESSION_INPUTIPC method, which calledsend_input. That writes the text LF-terminated, and LF is not the byte a terminal's Enter key sends — in a crossterm TUI in raw mode it's Ctrl+J, "insert a newline".Hit live while debugging #1189: a prompt sent to a codex session rendered in the pane, returned
{"ok":true}, and then nothing happened. No request reached the router; the text was sitting in the composer. It took a manual CR viaconstruct_send_keysto submit it. From the caller's side this is indistinguishable from a session that simply chose not to respond.Fix
The daemon already models this —
session_input_deliveryclassifies each harness, andinteractive_codex_takes_the_typed_submit_framingalready asserts codex needs typed submit. The service ingress path was fixed for exactly this reason and says so:The IPC dispatch never got the same treatment. Routing it through
deliver_user_textgives:send_input, unchangedTranscript recording is unaffected:
deliver_user_textrecords only for harnesses that don't mirror their own transcript, and codex reports its turn itself.Test
The regression is invisible from the caller's side — the old path returned
Ok— so asserting againstdeliver_user_textwould test the helper, not the wiring. The test drives a realSESSION_INPUTrequest throughdispatchagainst a codex-classified session with a mock PTY adapter, and asserts the recorded bytes contain the bracketed paste followed by a submit Enter.Verified it fails against the old wiring:
dispatchandSubCmdbecomepub(crate)so the test can reach that entry point.cargo test -p construct-daemon: 641 passed, 0 failed. Added lines are fmt-clean; both files carry pre-existing fmt drift onmainthat this PR leaves alone.Binary
crates/daemononly — ships inconstruct:/Users/moon/construct/.claude/worktrees/send-input-harness-framing/target/debug/constructNo visual change to record: the fix is that a send now starts a turn at all.