mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix(tui): stop slash dropdown from chopping last char of /goal (#31311)
Some checks are pending
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
Docker Build and Publish / build-amd64 (push) Waiting to run
Docker Build and Publish / build-arm64 (push) Waiting to run
Docker Build and Publish / merge (push) Blocked by required conditions
Docker Build and Publish / move-latest (push) Blocked by required conditions
Lint (ruff + ty) / ruff + ty diff (push) Waiting to run
Lint (ruff + ty) / ruff enforcement (blocking) (push) Waiting to run
Lint (ruff + ty) / Windows footguns (blocking) (push) Waiting to run
Nix / nix (macos-latest) (push) Waiting to run
Nix / nix (ubuntu-latest) (push) Waiting to run
Tests / test (1) (push) Waiting to run
Tests / test (2) (push) Waiting to run
Tests / test (3) (push) Waiting to run
Tests / test (4) (push) Waiting to run
Tests / test (5) (push) Waiting to run
Tests / test (6) (push) Waiting to run
Tests / save-durations (push) Blocked by required conditions
Tests / e2e (push) Waiting to run
Some checks are pending
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
Docker Build and Publish / build-amd64 (push) Waiting to run
Docker Build and Publish / build-arm64 (push) Waiting to run
Docker Build and Publish / merge (push) Blocked by required conditions
Docker Build and Publish / move-latest (push) Blocked by required conditions
Lint (ruff + ty) / ruff + ty diff (push) Waiting to run
Lint (ruff + ty) / ruff enforcement (blocking) (push) Waiting to run
Lint (ruff + ty) / Windows footguns (blocking) (push) Waiting to run
Nix / nix (macos-latest) (push) Waiting to run
Nix / nix (ubuntu-latest) (push) Waiting to run
Tests / test (1) (push) Waiting to run
Tests / test (2) (push) Waiting to run
Tests / test (3) (push) Waiting to run
Tests / test (4) (push) Waiting to run
Tests / test (5) (push) Waiting to run
Tests / test (6) (push) Waiting to run
Tests / save-durations (push) Blocked by required conditions
Tests / e2e (push) Waiting to run
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:
parent
2666009ccc
commit
a627981a65
3 changed files with 35 additions and 5 deletions
|
|
@ -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"}}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -187,10 +187,15 @@ export function FloatingOverlays({
|
|||
key={`${start + i}:${item.text}:${item.display}:${item.meta ?? ''}`}
|
||||
width="100%"
|
||||
>
|
||||
<Text bold color={theme.color.label}>
|
||||
{' '}
|
||||
{item.display}
|
||||
</Text>
|
||||
{/* flexShrink=0 — when meta overflows the row, Ink/Yoga
|
||||
otherwise shaves the last char off the display column
|
||||
(e.g. /goal renders as /goa). */}
|
||||
<Box flexShrink={0}>
|
||||
<Text bold color={theme.color.label}>
|
||||
{' '}
|
||||
{item.display}
|
||||
</Text>
|
||||
</Box>
|
||||
{item.meta ? (
|
||||
<Text
|
||||
backgroundColor={active ? theme.color.completionMetaCurrentBg : theme.color.completionMetaBg}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue