Skip to content

feat(desktop): arrow up/down history navigation in composer#39088

Closed
naqerl wants to merge 1 commit into
NousResearch:mainfrom
naqerl:feat/desktop-arrow-history-navigation
Closed

feat(desktop): arrow up/down history navigation in composer#39088
naqerl wants to merge 1 commit into
NousResearch:mainfrom
naqerl:feat/desktop-arrow-history-navigation

Conversation

@naqerl

@naqerl naqerl commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds ArrowUp/ArrowDown history navigation to the desktop composer's input. Pressing ArrowUp on an empty composer (or while already browsing) cycles backward through previously sent messages in the current session. ArrowDown cycles forward, restoring the original draft when reaching the "present". Stops at the oldest entry.

The user-text ring is derived from the live session messages on every press — no mirror, no seeding, no dedup. Single source of truth: $messages. The store only persists the per-session cursor and the saved draft.

Why derive instead of mirror: the previous mirror-based approach (push on submit, push on queue drain, push on voice submit) repeatedly fell out of sync with $messages — different paths used different session-id keys, the seed-on-first-press logic could push duplicates in the wrong order, and switching sessions required explicit cleanup. Deriving from $messages on every press eliminates the entire class of bugs by construction.

Related Issue

Fixes #38916

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)

Changes Made

  • apps/desktop/src/store/composer-input-history.ts (new, 158 lines) — deriveUserHistory, browseBackward, browseForward, resetBrowseState, isBrowsingHistory. Per-session cursor + draftSnapshot only; ring is computed lazily by the caller.
  • apps/desktop/src/store/composer-input-history.test.ts (new, 187 lines, 11 tests) — covers derivation, both browse directions, per-session isolation, mid-browse history changes (proves no mirror), session-switch reset.
  • apps/desktop/src/app/chat/composer/index.tsx (+81 lines) — imports the new store, subscribes to $messages as sessionMessages, adds a session-switch effect that resets the cursor, adds ArrowUp handler (with reordered guard: draft.trim() && !isBrowsingHistory(sessionId) returns early) and ArrowDown handler, calls resetBrowseState(sessionId) at the three submit sites (queue drain, regular submit, voice submit) so a new submit starts Arrow Up fresh.

How to Test

  1. Open a session, type "first message", submit.
  2. Type "second message", submit.
  3. Clear the composer. Press ArrowUp — composer shows "second message". Press ArrowUp again — "first message". Press ArrowUp again — no-op (oldest).
  4. Press ArrowDown twice — back to "first message", then "second message", then the original draft (or empty).
  5. Type a draft but don't submit. Press ArrowUp — does nothing (your draft is preserved).
  6. Submit something, then press ArrowUp. The just-submitted text should appear (since it's now in $messages).
  7. Switch to a different session. Press ArrowUp — starts from that session's ring, not the previous session's.

Run unit tests:

cd apps/desktop && npx vitest run src/store/composer-input-history.test.ts

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat(desktop): arrow up/down to navigate previous user messages)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've added tests for my changes
  • I've tested on my platform: macOS 15.2

Documentation & Housekeeping

  • I've considered cross-platform impact (Windows, macOS) — Electron app, no platform-specific code paths affected

Screenshots / Logs

$ npx vitest run src/store/composer-input-history.test.ts --environment jsdom
✓ src/store/composer-input-history.test.ts (11 tests) 26ms
Test Files  1 passed (1)
     Tests  11 passed (11)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(desktop): arrow up/down history navigation in composer

2 participants