fix(tui): stop slash dropdown from chopping last char of /goal (#31311)

Two independent bugs caused the slash-command autocomplete to render
`/goal` as `/goa` (and `/gquota` as `/gquot` for that matter) in the TUI:

1. `tui_gateway/server.py` was forwarding `c.display` from
   prompt_toolkit's `Completion` straight into the JSON-RPC payload.
   prompt_toolkit normalizes `display=` into `FormattedText` (a `list`
   subclass), so the wire format became `[["", "/goal"]]` instead of
   the `string` that `CompletionItem.display` in the TUI declares.
   `meta` already went through `to_plain_text` — `display` did not.

2. The dropdown row in `appOverlays.tsx` used `flexDirection="row"`
   with the display `<Text>` and the (very long) meta `<Text>` as
   siblings. When the meta overflows the row width, Ink/Yoga shrinks
   the *first* column by one cell, lopping the trailing character off
   the command name. `/goal` triggers it reliably because its meta
   string is the longest of any built-in command (description +
   embedded `[text | pause | resume | clear | status]` usage hint).
   Wrapping the display column in `<Box flexShrink={0}>` keeps it at
   its natural width and lets the meta wrap or truncate instead.
This commit is contained in:
brooklyn!
2026-05-24 00:12:55 -05:00
committed by GitHub
parent 2666009ccc
commit a627981a65
3 changed files with 35 additions and 5 deletions

View File

@@ -5382,7 +5382,12 @@ def _(rid, params: dict) -> dict:
items = [
{
"text": c.text,
"display": c.display or c.text,
# prompt_toolkit gives us FormattedText (a list of (style,
# text) tuples) for display/display_meta. Serialize both as
# plain strings — the TUI's CompletionItem.display contract
# is a string, and sending the raw list trips Ink's row
# layout into 1-char truncation of the next column.
"display": to_plain_text(c.display) if c.display else c.text,
"meta": to_plain_text(c.display_meta) if c.display_meta else "",
}
for c in completer.get_completions(doc, None)