Skip to content

ChatGPT device login cancels on non-cancel ESC-prefixed TUI input #41

Description

@mineru-zero

Problem

The /modelcodex (ChatGPT) device login flow can cancel immediately even when the user did not explicitly cancel.

The current login polling path treats any incoming terminal data containing a raw ESC byte as cancellation. In a TUI, ESC-prefixed input is common for non-cancel terminal events such as arrow keys, ANSI sequences, and SGR mouse reports. As a result, the Connect ChatGPT device-code card can disappear with Login cancelled. right after it appears.

Reproduction

  1. Start ourocode.
  2. Run /model.
  3. Select codex (ChatGPT) when it requires login.
  4. While the Connect ChatGPT device-code card is visible, send non-cancel ESC-prefixed terminal input such as an SGR mouse report.

Expected behavior

The Connect ChatGPT device-code card should remain visible until one of these happens:

  • the user explicitly cancels with Ctrl-C,
  • the user explicitly cancels with standalone Escape,
  • login succeeds,
  • the login flow times out.

Actual behavior

The card can disappear and the TUI logs Login cancelled. even though the user did not explicitly cancel.

Before / After evidence

The screenshots below are uploaded to GitHub and have the device code redacted.

Before and after comparison

Before

Before: login cancelled after SGR mouse input

After

After: Connect ChatGPT remains visible after SGR mouse input

Proposed fix

Decode login-time terminal input using the existing key decoder instead of checking raw ESC bytes directly:

  • Ctrl-C should cancel.
  • Standalone Escape should cancel.
  • SGR mouse reports should not cancel.
  • CSI arrow input should not cancel.
  • Incomplete ESC sequences should be buffered briefly instead of being treated as cancellation immediately.

Verification from the fix branch

The targeted tests passed locally:

mix test test/ourocode/terminal/tui_login_test.exs \
  test/ourocode/terminal/tui_model_selection_test.exs \
  test/ourocode/terminal/tui_frame_test.exs

Result: 41 passed

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions