mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Merge 31fc1d5294 into 00c3d848d8
This commit is contained in:
commit
620bf25ff8
3 changed files with 37 additions and 2 deletions
|
|
@ -730,6 +730,41 @@ def test_complete_slash_surfaces_completer_error(monkeypatch):
|
|||
assert "no completer" in resp["error"]["message"]
|
||||
|
||||
|
||||
def test_complete_slash_display_is_plain_string(monkeypatch):
|
||||
"""complete.slash must convert prompt_toolkit FormattedText display values
|
||||
to plain strings before sending them over RPC.
|
||||
|
||||
Regression: c.display is a FormattedText object, not a str. Passing it
|
||||
raw caused JSON serialization failures and broken rendering in the TUI
|
||||
completion dropdown.
|
||||
"""
|
||||
from prompt_toolkit.formatted_text import FormattedText
|
||||
|
||||
class _FakeCompletion:
|
||||
text = "/resume"
|
||||
display = FormattedText([("class:command", "/resume")])
|
||||
display_meta = FormattedText([("", "Resume a session")])
|
||||
|
||||
with patch("hermes_cli.commands.SlashCommandCompleter") as MockCompleter:
|
||||
instance = MockCompleter.return_value
|
||||
instance.get_completions.return_value = [_FakeCompletion()]
|
||||
|
||||
resp = server.handle_request(
|
||||
{"id": "1", "method": "complete.slash", "params": {"text": "/res"}}
|
||||
)
|
||||
|
||||
assert "result" in resp, resp
|
||||
items = resp["result"]["items"]
|
||||
assert len(items) >= 1
|
||||
item = next(i for i in items if i["text"] == "/resume")
|
||||
assert isinstance(item["display"], str), (
|
||||
"display must be a plain str — FormattedText breaks JSON serialization"
|
||||
)
|
||||
assert item["display"] == "/resume"
|
||||
assert isinstance(item["meta"], str)
|
||||
assert item["meta"] == "Resume a session"
|
||||
|
||||
|
||||
def test_input_detect_drop_attaches_image(monkeypatch):
|
||||
fake_cli = types.ModuleType("cli")
|
||||
fake_cli._detect_file_drop = lambda raw: {
|
||||
|
|
|
|||
|
|
@ -3650,7 +3650,7 @@ def _(rid, params: dict) -> dict:
|
|||
items = [
|
||||
{
|
||||
"text": c.text,
|
||||
"display": c.display or c.text,
|
||||
"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)
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ const ComposerPane = memo(function ComposerPane({
|
|||
<FloatingOverlays
|
||||
cols={composer.cols}
|
||||
compIdx={composer.compIdx}
|
||||
completions={composer.completions}
|
||||
completions={isBlocked ? [] : composer.completions}
|
||||
onModelSelect={actions.onModelSelect}
|
||||
onPickerSelect={actions.resumeById}
|
||||
pagerPageSize={composer.pagerPageSize}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue