fix(tui): keep a held Up key from crossing into prompt history - #3044
fix(tui): keep a held Up key from crossing into prompt history#3044bj456736 wants to merge 6 commits into
Conversation
A held Up key fires key-repeat events that walk the cursor to the top of a multi-line draft and then, without any deliberate keypress, carry the editor into prompt history — where a single stray edit silently drops the unsent draft. Detect held-key repeats (Kitty keyboard protocol event types where available, a 100ms inter-press heuristic elsewhere) and bar them from crossing from the draft into history; discrete presses keep the existing behavior, and once history is entered deliberately, repeats may keep browsing.
🦋 Changeset detectedLatest commit: 95f5505 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@codex review |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31c757600a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
… the guard On legacy terminals the first autorepeat arrives only after the keyboard's initial repeat delay (X11 defaults to 660ms, macOS/Windows up to ~1s), so it outruns the 100ms inter-press heuristic and still crosses from the draft into history. Arm a snap-back on such crossings: a repeat-classified Up arriving within the initial-delay window proves the hold and navigates back out to the draft. Crossings followed by deliberate navigation past the first entry are disarmed. Also register the held-Up guard as divergence MoonshotAI#9 in the pi-tui AGENTS.md local-divergence list so re-vendoring preserves it.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 72049b60cc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2c8686d3c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
A non-Up key between two Up presses proves the stream was interrupted, so the next Up must read as a fresh press rather than an autorepeat of the earlier one. Without the reset, Up → Down → quick Up failed to re-enter history. The multiple-browse-session test now exercises the reset path instead of masking it with a clock advance, and a dedicated regression test covers the interrupted-stream case.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ec2c3e613c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…nput
The chain reset lived in the base Editor's handleInput, but hosts also
break the stream outside it: programmatic setText ('') clears (e.g. the
Ctrl+C clear-draft path) and CustomEditor consumes shortcuts like Ctrl+C
before they ever reach super.handleInput. Expose resetUpArrowRepeatChain(),
call it from setText, and reset in CustomEditor for intercepted non-Up
keys. The setText history test now exercises the reset instead of
masking the stale timestamp with a clock advance; a new CustomEditor
test covers the intercepted-shortcut path.
8ccedd0 to
95f5505
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95f5505065
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
With the Kitty protocol the crossing event's press/repeat type is exact, so a press crossing is deliberate — arming the timing-based snap-back anyway made the first repeat of that same held key yank the editor back to the draft instead of continuing through history. Only arm when the Kitty protocol is inactive.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 087fb7f08f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const repeat = isKittyProtocolActive() | ||
| ? isKeyRepeat(data) | ||
| : gap < UP_ARROW_REPEAT_THRESHOLD_MS; |
There was a problem hiding this comment.
Fall back unless Kitty reports event types
When a terminal negotiates only a subset of the Kitty protocol flags, such as flag 1 without flag 2, terminal.ts still marks Kitty active for any nonzero flag set, while isKeyRepeat() is meaningful only with the report-event-types flag. In that environment every autorepeat arrives without :2 and is classified as a discrete press here, completely bypassing the held-Up history guard. Track whether negotiated flag 2 is enabled and use the timing heuristic when it is not.
AGENTS.md reference: packages/pi-tui/AGENTS.md:L17-L17
Useful? React with 👍 / 👎.
Problem
Holding ↑ to reach the top of a long unsent draft fires key-repeat events. The repeats walk the cursor to the first line, then keep going — crossing into prompt history without any deliberate keypress. One stray edit on a recalled entry (e.g. a space) then silently drops the unsent draft.
Fix
Detect held-key repeats and bar them from crossing from the draft into history:
Semantics after the change:
The companion fix (preserving the draft when a recalled history entry is edited) is intentionally not in this PR and will follow separately.
Tests
repeatevents are barred from entering history.tsc --noEmitclean; oxlint 0 errors; app-side custom-editor/editor-keyboard suites pass.