Skip to content

Fix/liar177 fix(terminal): fix AI agent input, cursor rendering, and status detection in the terminal - #40

Open
liar177 wants to merge 37 commits into
oso95:feat/bug-fixesfrom
liar177:fix/liar177-fix
Open

Fix/liar177 fix(terminal): fix AI agent input, cursor rendering, and status detection in the terminal#40
liar177 wants to merge 37 commits into
oso95:feat/bug-fixesfrom
liar177:fix/liar177-fix

Conversation

@liar177

@liar177 liar177 commented Sep 1, 2026

Copy link
Copy Markdown

Overview

This PR fixes a set of issues exposed when running AI agents such as Claude and Kimi inside the codirigent terminal,
centered on: cursor/input rendering errors, broken IME text input, inaccurate agent state detection, and a few minor
UI defects. Every change is covered by regression tests.

Changes

  1. Cursor rendering errors (verified primarily against Claude and Kimi; other AI agents have not been tested)
    • Claude (Ink) draws its own input caret as a reverse-video blank \e[7m \e[27m, which was previously discarded as a
      default-background blank cell, causing the caret to vanish and the input position to jump (e.g. to the far
      right). We now keep INVERSE blanks and render them as caret blocks.
    • Rebuild terminal row caches when switching the alternate screen to avoid stale rows; accumulate pending dirty
      rows across consecutive snapshots for correct dynamic refresh.
  2. Inaccurate agent state detection
    • Generalized agent state detection rules: correctly distinguish "awaiting approval" from "response ready" visible
      terminal semantics, and map Claude's idle notification to "response ready".
    • Ignore PowerShell prompts in generic attention detection; normalize and validate Windows hook executable paths
      before registration.
  3. Broken IME and text input
    • The task-creation modal could not accept IME Chinese input nor direct text input; we now register input handlers
      for every input field, correctly route IME composition and committed Unicode text, while preserving direct
      English/digit/space input.
    • Anchor in-terminal IME preedit to the soft caret position of a hidden cursor; sync ConPTY size before restored
      agents start; forward terminal editing control keys (arrows, backspace, etc.) while preserving app shortcuts.
  4. Minor UI defects
    • The update toast intercepted terminal mouse events (click-through); we now occlude the toast from mouse input and
      add hit-testing regression coverage.

Testing

Each commit adds corresponding regression tests covering cursor rendering, size sync, session resume, focus, key
handling, state detection, IME input, and hit-testing.

cian-lien and others added 30 commits March 15, 2026 19:26
docs: add Simplified Chinese README translation
…re active

On macOS, adds applicationShouldTerminate: to GPUI's delegate via ObjC
runtime, returning NSTerminateCancel when sessions exist (triggers the
system "failed to quit" dialog). On Windows, subclasses the GPUI window
to intercept WM_QUERYENDSESSION with ShutdownBlockReasonCreate.
User-initiated quit (Cmd+Q / Ctrl+Q) always proceeds immediately.
Check the WRAPLINE flag on each grid row before inserting a newline
during copy. Wrapped rows are continuations of the same logical line
and should be joined without a newline, matching standard terminal
emulator behavior.
Cast through *const () before isize to satisfy
fn-to-numeric-cast and function-casts-as-integer lints.
- Add CI step to stamp workspace version from the release tag before
  building, so env!("CARGO_PKG_VERSION") reflects the actual release
- Replace hardcoded "v0.1.0" in settings panel with dynamic version
- Fix Windows rustfmt for shutdown_guard_windows.rs
GPUI's Window has an inherent window_handle() returning AnyWindowHandle
that shadows the HasWindowHandle trait method returning Result. Use
HasWindowHandle::window_handle(window) to call the trait method.
… resize

Empty terminal rows use the default background color and produce no
bg_rects_hsla entries, so they showed the panel_bg from the outer div
rather than the terminal background color. This was visible as a visual
cut-off when dragging a session from a smaller pane into a larger one.

Fix by painting the full canvas bounds with terminal_bg at the start of
the paint closure, before any cell-specific backgrounds. Non-default
background cells still paint their own color on top, as before.
…ling

When new output arrives while the viewport is scrolled into scrollback,
alacritty's partial damage tracking only reports rows changed in the
active area. But new output can push lines into scrollback, shifting all
content visible in the scrolled viewport. Using partial damage leaves
most rows stale, causing a cycling/repeating display artifact.

Skip the partial-damage optimization when display_offset > 0 so all
viewport rows are rebuilt from the current grid state.
When multiple signal files target the same session (e.g., parent + subagent),
non-deterministic read_dir order could let a stale "idle" from the parent
overwrite a newer "working" from the subagent, keeping the status stuck on idle.
On app restart, finalize_restored_session_bootstrap overwrote the workspace
session's session_uuid with the old UUID from state.json. But the PTY was
already spawned with the new UUID from Session::new() as the
CODIRIGENT_SESSION_UUID env var. This mismatch caused hook signal routing
to fail silently — signals carried the PTY's UUID but the workspace had the
old one — keeping status stuck on Idle.
- Add sign-and-upload.ps1 script for local MSI signing with Certum cert
- Add windows-release-signing.md documenting the full signing workflow
- Exclude MSI from CI checksums (replaced by signed version post-build)
- Reorganize docs into features/, release/, workflows/ subdirectories
- Remove obsolete plan files and gitignore specs/
fix: terminal display cutoff and rendering issues
- Release workflow now creates draft releases for manual review
- Remove author attribution from README
- Update SmartScreen warning to reflect code-signed MSI
On Windows, GPUI 0.2.x's WindowControlArea::Drag causes WM_NCHITTEST
to return HTCAPTION, which makes Windows enter a modal drag loop inside
DefWindowProc. This re-enters the message pump while GPUI still holds
RefCell borrows, causing a panic/freeze (issue oso95#31).

Fix: on Windows, do NOT use WindowControlArea::Drag at all. Instead,
post WM_NCLBUTTONDOWN(HTCAPTION) asynchronously via PostMessageW from
an on_mouse_down handler, so the modal drag loop starts on the next
message-pump iteration after GPUI's borrows are released.

Also moves logo/title into a dedicated drag_region child div (cleaner
separation from caption buttons) and adds double-click-to-maximize
support on both platforms.

Closes oso95#31
Reuses the existing session dropdown menu (rename, groups, end session)
when right-clicking a tab, positioned at the cursor location.
The field was intentionally kept unused after the UUID overwrite fix
(8d746d3) but never cleaned up. Removing it along with the stale
NOTE comment and all construction sites.
The rename and group assignment modals used append-only text input
with no cursor positioning. Add cursor_position tracking to
SessionActionModal, reusing the existing cursor helper methods from
the task creation modal.

Supports: left/right arrows, Home/End, Delete, backspace and insert
at cursor position, and Ctrl+V paste.
Covers the full release process: tagging, CI draft creation, local
MSI code signing with SimplySign/Certum, checksum updates, and
publishing. Includes troubleshooting and recovery steps.
PostMessageW(WM_NCLBUTTONDOWN, HTCAPTION, 0) passed lparam=0 meaning
cursor position (0,0). Some Windows builds silently ignore the message
when the position falls outside the window bounds. Now calls
GetCursorPos and packs screen coordinates into lparam.
canvas_metrics Rc<Cell<>> is only populated during prepaint, so
content_height is always 0 when render_terminal_scrollbar runs.
Use rows * cell_height as the render-time estimate. Mouse handlers
still prefer the real content_height from prepaint when available.
High-resolution touchpad momentum scrolling produced delta_y values of
500+ pixels, translating to 30+ lines per event — causing page-sized
jumps. Cap to half the viewport height.

Also reduce snap-to-bottom threshold from rows+lines (~30 rows) to
3+lines so it only triggers when genuinely near the bottom, fixing the
infinite scroll feel.
… Windows

GPUI 0.2.x re-dispatches WM_NCLBUTTONDOWN through its element tree before
DefWindowProc can process it. When the title bar's on_mouse_down handler
catches the event, DefWindowProc never runs — breaking both window drag
(PostMessageW loop) and top-edge resize (drag region overlaps resize zone).

Replace the direct PostMessageW(WM_NCLBUTTONDOWN) approach with a Win32
window subclass (SetWindowSubclass) that intercepts NC messages before
GPUI's WndProc:

- Drag: on_mouse_down posts a custom WM_APP message; the subclass catches
  it and calls DefWindowProc(WM_NCLBUTTONDOWN, HTCAPTION) directly, starting
  the OS drag loop when no GPUI borrows are held.
- Resize: WM_NCLBUTTONDOWN for resize edges (HTTOP, HTLEFT, …) routes
  straight to DefWindowProc, bypassing GPUI's element dispatch.
- Buttons: WM_NCLBUTTONDOWN for HTMINBUTTON/HTMAXBUTTON/HTCLOSE passes
  through to GPUI for normal handling.

Fixes window drag not working on some Windows machines and top-edge resize
being eaten by the title bar's mouse handler.
After a double-click, the WM_APP_DRAG_WINDOW from the first click may
still be in the message queue when titlebar_double_click() has already
maximized/restored the window. Check GetAsyncKeyState(VK_LBUTTON)
before starting the drag — if the button is released, skip the stale
message to avoid a spurious drag on the now-toggled window.
…n restart

The resume command (claude --resume) was sent to the PTY immediately after
bootstrapping, before the shell had completed its DSR handshake. The buffered
command bytes corrupted PowerShell's cursor position query, leaving terminals
blank. Now resume commands are enqueued and dispatched only after the shell
produces its first output, with a 3-second fallback timeout.
oso95 and others added 7 commits July 8, 2026 20:50
fix: include Nerd Font family fonts in Windows terminal font detection
1. Normalize and validate Windows hook executable paths before registration.
2. Ignore PowerShell shell prompts in generic attention detection.
3. Rebuild terminal row caches when switching alternate screens.
4. Accumulate pending dirty rows across consecutive snapshots.
1. Classify visible terminal semantics for approval and response-ready states
2. Preserve legacy prompt patterns and support extensible status rules
3. Map Claude idle notifications to response ready
4. Add detector, UI, hook regressions and documentation
1. Register input handlers for all task creation fields.

2. Route IME composition and committed Unicode text correctly.

3. Preserve direct English, digit, and space input with regression tests.
1. Exclude INVERSE-flagged blank cells from the default-background skip path so TUIs that draw their caret as a reverse-video blank (e.g. claude's Ink `\e[7m \e[27m`) render it as a background rect instead of being discarded.
2. Add a regression test asserting a reverse-video blank produces a caret background rect.
1. Occlude the update toast from terminal mouse input.\n2. Add GPUI hit-testing regression coverage.
1. Anchor IME preedit to hidden-cursor software carets.\n2. Synchronize ConPTY size before restored agents start.\n3. Forward terminal editing control keys while preserving app shortcuts.\n4. Add cursor, resize, resume, focus, and key regression coverage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants