fix(tui): stop double-formatting friendly tool labels (#62796) - #62816
fix(tui): stop double-formatting friendly tool labels (#62796)#62816PRATHAMESH75 wants to merge 2 commits into
Conversation
Since NousResearch#55166 the gateway's `_tool_ctx` returned a complete friendly label ("Reading package.json L1-300") under the `context` field, which Ink then wrapped again via `formatToolCall`, producing `Read File("Reading package.json L1-300")` on live, completed-trail, and resumed rows. Restore `context` to a raw argument preview and ship the complete phrase in an additive `label` field. Ink renders `label` verbatim when present and otherwise falls back to wrapping `context`, so pre-`label` clients, custom/MCP tools, disabled friendly labels, and desktop rendering are all unaffected. Fixes NousResearch#62796.
Duplicate of #62809 — twin fresh PR fixing the same issue (#62796) via the same mechanism (split the raw |
|
Thanks for tracing the regression through both the gateway and Ink rendering paths. The premise is confirmed on current main: Problems
Suggested changes
Automated hermes-sweeper review. |
The tool.start payload now carries an optional label (the complete friendly label rendered verbatim) distinct from the raw context preview. Document it in the protocol event table so the contract is complete.
|
Addressed the review: documented the optional |
|
Heads-up on the current Since this PR was opened, upstream reworked the I'm intentionally not force-resolving this, because it isn't additive: naively keeping both fields would leave two parallel label paths, and it's a real question whether the new Suggested next step for whoever picks this up: check whether double-formatting still reproduces on current |
Correction: the prior duplicate conclusion is cleared. The current head added the requested protocol documentation, but it now conflicts with main's TranscriptRow/display schema rework. It is related to #62809, yet a maintainer must decide whether the current renderer already resolves the bug or whether to re-port the fix via |
|
Following up on the open question from the previous note — I checked, and the double-formatting is now fixed on The fix landed in f0031ab ("fix(gateway): send a raw arg preview on tool.start, not a phrased label", by @OutThisLife). Verified f0031ab is on |
What does this PR do?
The TUI double-formats built-in tool rows: instead of
Reading package.json L1-300it showsRead File("Reading package.json L1-300")(and likewiseSkill View("Reading skill …"),Web Extract("Reading …"),Search Files("Searching files for …")).Since #55166, the gateway's
_tool_ctxreturned a complete friendly label under the wire'scontextfield, butcontextis a contract for a raw argument preview that clients wrap themselves asRead File("…"). Ink dutifully wrapped the already-complete label a second time.This restores
contextto a raw preview and ships the complete phrase in an additivelabelfield. Clients renderlabelverbatim when present and otherwise fall back to wrappingcontext— so pre-labelgateways/clients, custom/plugin/MCP tools (no curated verb), disableddisplay.friendly_tool_labels, and the desktop's own localized rendering are all unaffected. This is the approach suggested by the reporter (@CNSeniorious000) in the issue.Related Issue
Fixes #62796
Type of Change
Changes Made
tui_gateway/server.py:_tool_ctxnow returns the raw preview (build_tool_preview) again; new_tool_labelreturns the complete friendly label only when it differs from that preview. Both the livetool.startpayload and the resumed-history tool message now carrycontext(raw) plus an optionallabel.ui-tui/src/lib/text.ts:formatToolCall(name, context, friendlyLabel?)rendersfriendlyLabelverbatim when present;buildToolTrailLine/buildVerboseToolTrailLinethread it through so the completed/resumed trail matches the live row.ui-tui/src/app/turnController.ts,createGatewayEventHandler.ts,domain/messages.ts,types.ts,gatewayTypes.ts: carry the newlabelfrom the gateway event / transcript row to the render helpers.ui-tui/src/components/thinking.tsx: render the live row fromlabel; make the inline-subagent delegate-group detection accept both the wrappedDelegate Task(…)and the friendlyDelegating …phrasings._on_tool_startand assertscontextstays a bare preview whilelabelcarries the complete phrase (and is omitted for unlabeled tools), plus TS tests forformatToolCall, the trail line, and resumed-transcript rendering. Updatedtest_history_to_messages_preserves_tool_calls_for_resume_displayto the corrected contract.How to Test
Result: 319 passed (includes the two new composition tests).
TS (from
ui-tui/, afternpm install+npm run build --prefix packages/hermes-ink):Result: all pass. (Pre-existing, unrelated failures in
statusRule.test.ts/virtualHeights.test.tsreproduce on cleanupstream/main.)Manual: with
display.friendly_tool_labels: true(default), runhermes --tui, triggerread_file, and observe the live row, completion trail, and a resumed transcript all showReading package.json L1-300— notRead File("Reading package.json L1-300").Checklist
Code
Documentation & Housekeeping
cli-config.yaml.exampleif I added/changed config keys — N/A (no config keys)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/ACredits
Root cause and the
context+ additivelabelfix strategy were diagnosed by @CNSeniorious000 in #62796; this PR implements that approach.