diff --git a/tests/test_tui_gateway_server.py b/tests/test_tui_gateway_server.py
index 2824bd85916..3328110b2be 100644
--- a/tests/test_tui_gateway_server.py
+++ b/tests/test_tui_gateway_server.py
@@ -1619,6 +1619,26 @@ def test_complete_slash_includes_provider_alias():
assert any(item["text"] == "provider" for item in resp["result"]["items"])
+def test_complete_slash_returns_plain_string_fields():
+ # prompt_toolkit hands us FormattedText (a list subclass) for
+ # display/display_meta; the TUI's CompletionItem contract is plain
+ # strings, and shipping the raw list trips Ink's row layout into
+ # 1-char truncation of the next column (/goal → /goa).
+ resp = server.handle_request(
+ {"id": "1", "method": "complete.slash", "params": {"text": "/g"}}
+ )
+
+ items = resp["result"]["items"]
+ goal = next((it for it in items if it["text"] == "goal"), None)
+ assert goal is not None
+ assert isinstance(goal["display"], str), goal["display"]
+ assert isinstance(goal["meta"], str), goal["meta"]
+ assert goal["display"] == "/goal"
+ for item in items:
+ assert isinstance(item["display"], str), item
+ assert isinstance(item["meta"], str), item
+
+
def test_complete_slash_includes_tui_details_command():
resp = server.handle_request(
{"id": "1", "method": "complete.slash", "params": {"text": "/det"}}
diff --git a/tui_gateway/server.py b/tui_gateway/server.py
index 82107b7c05b..15dbf19ddeb 100644
--- a/tui_gateway/server.py
+++ b/tui_gateway/server.py
@@ -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)
diff --git a/ui-tui/src/components/appOverlays.tsx b/ui-tui/src/components/appOverlays.tsx
index c12624a4bf8..7fd14563a99 100644
--- a/ui-tui/src/components/appOverlays.tsx
+++ b/ui-tui/src/components/appOverlays.tsx
@@ -187,10 +187,15 @@ export function FloatingOverlays({
key={`${start + i}:${item.text}:${item.display}:${item.meta ?? ''}`}
width="100%"
>
-
- {' '}
- {item.display}
-
+ {/* flexShrink=0 — when meta overflows the row, Ink/Yoga
+ otherwise shaves the last char off the display column
+ (e.g. /goal renders as /goa). */}
+
+
+ {' '}
+ {item.display}
+
+
{item.meta ? (