Bug Description
Content appended by a transform_llm_output plugin hook is silently dropped when Hermes CLI streams a response token-by-token. The appended content is present in the final response text and stored in conversation history, but the user never sees it on screen.
Steps to Reproduce
- Install a plugin that implements
transform_llm_output and appends a suffix to the response (e.g. a disclaimer, citation, or additional content).
- Run
hermes in interactive CLI mode (streaming enabled by default).
- Send any message that triggers the plugin to append content.
- Observe that only the streamed response is shown — the appended content is missing from the terminal output.
To confirm the content is actually there: check conversation history or run in a non-streaming surface (Dashboard, Desktop, TUI). The appended content appears correctly on all non-streaming surfaces.
Expected Behavior
After streaming completes and transform_llm_output fires, any content the plugin appended to the response should be printed to the terminal.
Actual Behavior
The CLI enters the already_streamed branch after streaming and skips all output with pass. Since transform_llm_output fires after the stream is closed, the plugin's appended content is never displayed.
Relevant code in cli.py:
elif already_streamed:
# Response was already streamed token-by-token with box framing;
# _flush_stream() already closed the box. Skip Rich Panel.
pass # ← appended content is silently dropped here
Root Cause Analysis
The sequence is:
- CLI streams response token-by-token and sets
already_streamed = True.
- After the tool loop,
finalize_turn() fires transform_llm_output hooks.
- A plugin appends content, returning the full new response string.
finalize_turn() returns the transformed response in the result dict.
- Back in the CLI, the
already_streamed branch executes pass — the transformed response with appended content is discarded from the display path.
The fix requires two small changes:
agent/turn_finalizer.py — capture the pre-transform response so the CLI knows what was already streamed:
_pre_transform_response = None
# ... inside the transform loop ...
for _hook_result in _transform_results:
if isinstance(_hook_result, str) and _hook_result:
_pre_transform_response = final_response # save before overwrite
final_response = _hook_result
_response_transformed = True
break
# ... in the result dict ...
"response_transformed": _response_transformed,
"pre_transform_response": _pre_transform_response, # new field
cli.py — in the already_streamed branch, print only the appended suffix:
elif already_streamed:
if result and result.get("response_transformed"):
_pre = result.get("pre_transform_response") or ""
_appended = response[len(_pre):]
if _appended.strip():
_cprint(_appended)
A PR with this fix is ready: https://github.com/kweiner/hermes-agent/tree/fix/transform-llm-output-streaming
Debug Report
N/A — this is a code-level bug with a clear root cause, not a configuration or environment issue.
Operating System
Ubuntu 24.04.4 LTS
Python Version
3.11.15
Hermes Version
0.18.0
Are you willing to submit a PR for this?
Bug Description
Content appended by a
transform_llm_outputplugin hook is silently dropped when Hermes CLI streams a response token-by-token. The appended content is present in the final response text and stored in conversation history, but the user never sees it on screen.Steps to Reproduce
transform_llm_outputand appends a suffix to the response (e.g. a disclaimer, citation, or additional content).hermesin interactive CLI mode (streaming enabled by default).To confirm the content is actually there: check conversation history or run in a non-streaming surface (Dashboard, Desktop, TUI). The appended content appears correctly on all non-streaming surfaces.
Expected Behavior
After streaming completes and
transform_llm_outputfires, any content the plugin appended to the response should be printed to the terminal.Actual Behavior
The CLI enters the
already_streamedbranch after streaming and skips all output withpass. Sincetransform_llm_outputfires after the stream is closed, the plugin's appended content is never displayed.Relevant code in
cli.py:Root Cause Analysis
The sequence is:
already_streamed = True.finalize_turn()firestransform_llm_outputhooks.finalize_turn()returns the transformed response in the result dict.already_streamedbranch executespass— the transformed response with appended content is discarded from the display path.The fix requires two small changes:
agent/turn_finalizer.py— capture the pre-transform response so the CLI knows what was already streamed:cli.py— in thealready_streamedbranch, print only the appended suffix:A PR with this fix is ready: https://github.com/kweiner/hermes-agent/tree/fix/transform-llm-output-streaming
Debug Report
N/A — this is a code-level bug with a clear root cause, not a configuration or environment issue.
Operating System
Ubuntu 24.04.4 LTS
Python Version
3.11.15
Hermes Version
0.18.0
Are you willing to submit a PR for this?