Skip to content

fix: /reasoning command output ordering, display, and inline think extraction#1031

Merged
teknium1 merged 2 commits intomainfrom
hermes/hermes-3a9bd319
Mar 12, 2026
Merged

fix: /reasoning command output ordering, display, and inline think extraction#1031
teknium1 merged 2 commits intomainfrom
hermes/hermes-3a9bd319

Conversation

@teknium1
Copy link
Contributor

@teknium1 teknium1 commented Mar 12, 2026

Summary

Fixes the /reasoning command across both CLI and gateway (Telegram/Discord/etc).

Problem

  1. Gateway had no /reasoning command at all — messaging platform users had no way to view or change reasoning settings
  2. CLI output interleaving — command echo used print() while feedback used _cprint(), causing output to render out-of-order under prompt_toolkit
  3. Reasoning display never showed/reasoning show toggled a flag but reasoning was never captured from models using inline <think> blocks
  4. Show/hide wasn't persisted/reasoning show was session-only, lost on restart

Changes

Gateway (gateway/run.py)

  • New /reasoning command with full feature parity:
    • No args: shows current effort level + display state
    • /reasoning <level>: sets effort (none/low/medium/high/xhigh), saved to config
    • /reasoning show|hide: toggles reasoning display, saved to config
  • Reasoning display in responses: when enabled, prepends a 💭 Reasoning block with the model's thinking before the response (collapses >15 lines)
  • Plumbing: last_reasoning propagated through _run_agent return dict, _show_reasoning loaded from config at startup, added to help text

CLI (cli.py)

  • Fixed output ordering: changed command echo from print() to _cprint() so echo and feedback render through the same path
  • Persist show/hide: /reasoning show|hide now saves to display.show_reasoning in config
  • Clearer feedback: added ✓ checkmarks, aligned status columns

Agent Core (run_agent.py)

  • Inline <think> block extraction: when _extract_reasoning() finds no structured API-level reasoning fields, falls back to extracting <think>...</think> blocks from the response content
  • This feeds into both the reasoning callback (during tool loops) and the post-response reasoning box/display

Tests

  • 7 new tests for inline think block extraction (41 total in test_reasoning_command.py)
  • Full suite: 3144 passed, 618 gateway tests passed

…traction

Three issues with the /reasoning command:

1. Output interleaving: The command echo used print() while feedback
   used _cprint(), causing them to render out-of-order under
   prompt_toolkit's patch_stdout. Changed echo to use _cprint() so
   all output renders through the same path in correct order.

2. Reasoning display not working: /reasoning show toggled a flag
   but reasoning never appeared for models that embed thinking in
   inline <think> blocks rather than structured API fields. Added
   fallback extraction in _build_assistant_message to capture
   <think> block content as reasoning when no structured reasoning
   fields (reasoning, reasoning_content, reasoning_details) are
   present. This feeds into both the reasoning callback (during
   tool loops) and the post-response reasoning box display.

3. Feedback clarity: Added checkmarks to confirm actions, persisted
   show/hide to config (was session-only before), and aligned the
   status display for readability.

Tests: 7 new tests for inline think block extraction (41 total).
The /reasoning command only existed in the CLI — messaging platforms
had no way to view or change reasoning settings. This adds:

1. /reasoning command handler in the gateway:
   - No args: shows current effort level and display state
   - /reasoning <level>: sets reasoning effort (none/low/medium/high/xhigh)
   - /reasoning show|hide: toggles reasoning display in responses
   - All changes saved to config.yaml immediately

2. Reasoning display in gateway responses:
   - When show_reasoning is enabled, prepends a 'Reasoning' block
     with the model's last_reasoning content before the response
   - Collapses long reasoning (>15 lines) to keep messages readable
   - Uses last_reasoning from run_conversation result dict

3. Plumbing:
   - Added _show_reasoning attribute loaded from config at startup
   - Propagated last_reasoning through _run_agent return dict
   - Added /reasoning to help text and known_commands set
   - Uses getattr for _show_reasoning to handle test stubs
@teknium1 teknium1 merged commit e782b92 into main Mar 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant