Skip to content

Ankit c cloud tui poc a2bc - #905

Open
ankit-thesys wants to merge 12 commits into
thesysdev:mainfrom
ankit-thesys:ankit-c-cloud-tui-poc-a2bc
Open

Ankit c cloud tui poc a2bc#905
ankit-thesys wants to merge 12 commits into
thesysdev:mainfrom
ankit-thesys:ankit-c-cloud-tui-poc-a2bc

Conversation

@ankit-thesys

Copy link
Copy Markdown
Contributor

What

Describe the change and why it is needed.

Changes

Test Plan

Describe how you validated this change.

  • Not applicable (explain why)
  • Verified locally

Checklist

  • I linked a related issue, if applicable
  • I updated docs/README when needed
  • I considered backwards compatibility

cursoragent and others added 12 commits July 30, 2026 08:41
examples/openui-tui-chat: a terminal chat client that streams OpenUI Lang
from an OpenAI-compatible model and renders it as an interactive Ink TUI.
Reuses @openuidev/lang-core (streaming parser + runtime) and
@openuidev/react-headless (chat store + streaming adapter); adds an Ink
component library, tree walker, and keyboard focus/action handling.
Includes vitest + ink-testing-library tests for rendering and interactivity.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
ChatProvider from react-headless resolved the workspace's react@19 while Ink's
reconciler uses react@18, causing a dual-React 'invalid hook call' crash. Drop
ChatProvider/useThread and add a small local chat store (src/chat.ts) that runs
on Ink's own React while still reusing react-headless's DOM-free streaming
pipeline (processStreamedMessage + openAIReadableStreamAdapter).

Co-authored-by: Ankit Das <www.das5471@gmail.com>
- Preserve full conversation history via Ink <Static> (completed turns are
  emitted once to scrollback), fixing the tall-output/composer-scroll issue
  and keeping the composer anchored at the bottom.
- Split interactive components into interactive vs display-only variants (via
  a context flag) so finalized turns don't pollute keyboard focus.
- Add chat framing: header bar, user bubbles, assistant labels, welcome/empty
  state, an animated streaming spinner, and a bordered composer with hints.
- Add a test covering display-only (finalized) rendering.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
The dropdown required arrow-then-Enter and gave no immediate visual feedback
(the (•) only appeared after focus moved away), so selection felt broken.
Now arrow keys select immediately (radio-group style) and a local state bump
guarantees an instant repaint even when the cursor index is unchanged. Also
initialize the cursor to the current selection and add a form usage hint.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
Options are numbered (1., 2., …) and pressing the matching digit selects that
option directly — no arrow navigation or Enter required. Arrow keys and Enter
still work. Updates the focused-select and form hints accordingly.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
Adds a click-only SGR mouse layer (src/genui/mouse.tsx): enables ?1000/?1006
once at the root, parses left-button presses, and hit-tests them against the
bottom-anchored live region via Yoga layout offsets (offset recomputed per
click so it adapts as content changes). Clicking selects a dropdown option,
activates a button/follow-up, or focuses a text field. Text inputs and the
composer now filter escape/mouse sequences out of stdin so mouse bytes don't
leak into fields. Keyboard remains the primary, fully-portable interaction.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
Mouse clicks were only landing when the conversation had filled the screen;
a short/fresh form rendered near the top, but hit-testing assumed the live
region was bottom-anchored, so clicks missed. Give the live region the full
terminal height with justifyContent=flex-end so it always fills the screen
(top at row 0). The click offset then computes to 0 and zone positions equal
screen coordinates, so clicks land correctly regardless of content length.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
…tic>

The full-height live region plus <Static> made Ink repaint and scroll the whole
screen on every keystroke (flicker + jumping). Render the current exchange in a
single fixed full-height frame instead: Ink updates it in place without
scrolling, so typing is stable, and because the frame fills the screen from the
top, mouse clicks still map 1:1 to screen rows. Trade-off: only the current
exchange is shown on screen (no scrollback history of prior turns).

Co-authored-by: Ankit Das <www.das5471@gmail.com>
Bring back the multi-turn history that was dropped when fixing the flicker.
Render finished turns via Ink <Static> (terminal scrollback) with a small
natural-height live region — the combination that was smooth in earlier
versions. Trade-off: mouse hit-testing becomes best-effort (reliable once the
conversation fills the screen); keyboard works everywhere. Documented the
history-vs-mouse trade-off in the README.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
- Full-screen: render on the terminal alternate screen (cli.tsx) with a single
  full-height frame showing the current exchange (no scrollback history). This
  gives reliable pixel-perfect mouse (offset 0) and minimal flicker.
- Richer visuals via the Ink ecosystem: a self-contained truecolor GradientText
  (gradient.tsx) on the header, headings, chart bars and the assistant label;
  ink-spinner for the streaming indicator; ink-big-text for the welcome splash.
- New OpenUI components: Callout (colored banner) and TagBlock (colored pills),
  wired into the library so the model can emit them. Tests strip ANSI and cover
  the new components.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
…me + DSR)

A form taller than the terminal broke the fixed-height/alt-screen layout
(overflow corrupted the frame; Ink can't reliably clip). Render the exchange at
natural height instead, so long content scrolls in the terminal's native
scrollback and the layout stays intact. Removed the alternate screen (native
scrollback is needed for long forms) and the DSR cursor-position probe (its
responses leaked into the composer as garbage). Mouse hit-testing bottom-anchors
to the live region, which is correct for screen-filling content incl. long forms.

Co-authored-by: Ankit Das <www.das5471@gmail.com>
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.

2 participants