Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/substrate/tasks/tui-message-interactions.md
Fimeg e480809c70 docs: rescue the agent-substrate tree out of a gitignored directory
219 files, 2.0 MB, untracked in souveraine/docs and existing nowhere else.
The volume is at 100% with no snapshots.
2026-07-26 12:11:50 -04:00

2.3 KiB

title status priority created owner
TUI message interactions — click-to-copy, click-to-cockpit scoped medium 2026-05-12 next-instance

Artifact

When the user clicks (mouse) on a chat message or a tool card, the TUI:

  1. Copies the message text to the system clipboard (visual confirmation flash on the message).
  2. If the message has a paired N+1 / reasoning / surfacing entry, scrolls the cockpit panel to that entry and briefly highlights it.

Keyboard parity: y while a message is "hovered" by index does the same copy; Tab + j/k cycles cockpit linkage.

Why now

Already raised in the broad-stroke session (2026-05-12). Casey said: "request to be able to click on a message, copy button / or when click on message that the thinking / subconscious cockpit sections track."

Scope

Three small pieces:

A. Click hit-testing

src/ui/chat.rs::draw_messages already builds lines linearly. To make click work we need to annotate each visible message with a Rect it occupies after scroll. Build a Vec<(MessageId, Rect)> while emitting lines and stash it on ChatState::message_hitboxes. Update on every draw_messages call. ChatMessage gains a stable id: u64 (monotonic).

B. Mouse event plumbing

src/main.rs event loop currently reads crossterm::event::Event::Key. Enable mouse capture (crossterm::execute!(stdout, EnableMouseCapture)) and route Event::Mouse to ChatState::handle_mouse(x, y, kind). On MouseEventKind::Down(Left), look up the hitbox, set selected_message, and trigger the copy.

C. Clipboard + cockpit jump

  • Add arboard = "3" to Cargo.toml. The lazy-init pattern: hold an Option<Arboard> on ChatState, log-warn on failure (Wayland may need wl-clipboard fallback).
  • On copy: flash the bubble border for ~600ms (set flash_until: Instant on the message, fade in draw_messages).
  • On cockpit jump: every ChatMessage::Tool, Surfacing, etc. carries an optional cockpit_anchor: Option<usize> (index into cockpit_log). Clicking scrolls cockpit_scroll to that anchor.

Out of scope

  • Selection across multiple messages — first cut copies one message at a time.
  • Rich clipboard formats (HTML/RTF). Plain text only.

Token plan

Opus to scope the hitbox-as-side-channel design. Sonnet to wire arboard, mouse capture, and the flash animation — all mechanical once the shape is decided.