mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-27 11:22:03 +00:00
feat(discord): render reasoning as -# subtext via display.reasoning_style (#51168)
Adds a per-platform display.reasoning_style setting (code | blockquote | subtext) controlling how the show_reasoning summary renders on the gateway. Discord defaults to "subtext" (-# small grey metadata text); every other platform keeps the fenced code block. Resolves through the existing display.platforms.<platform>.reasoning_style override chain.
This commit is contained in:
parent
f32be4439c
commit
6cc07b6cd0
4 changed files with 89 additions and 2 deletions
|
|
@ -34,6 +34,12 @@ _GLOBAL_DEFAULTS: dict[str, Any] = {
|
|||
"tool_progress": "all",
|
||||
"tool_progress_grouping": "accumulate", # "accumulate" = edit one bubble; "separate" = one msg per tool
|
||||
"show_reasoning": False,
|
||||
# How a reasoning/thinking summary is rendered when show_reasoning is on.
|
||||
# "code" -> 💭 **Reasoning:** + fenced code block (legacy default)
|
||||
# "blockquote"-> each line prefixed with "> "
|
||||
# "subtext" -> each line prefixed with "-# " (Discord small grey subtext)
|
||||
# Discord defaults to "subtext"; everywhere else defaults to "code".
|
||||
"reasoning_style": "code",
|
||||
"tool_preview_length": 0,
|
||||
"streaming": None, # None = follow top-level streaming config
|
||||
# Gateway-only assistant/status chatter controls. These default on for
|
||||
|
|
@ -111,7 +117,10 @@ _PLATFORM_DEFAULTS: dict[str, dict[str, Any]] = {
|
|||
"tool_progress": "off",
|
||||
"busy_ack_detail": False,
|
||||
},
|
||||
"discord": _TIER_HIGH,
|
||||
# Discord has a native "subtext" primitive (-# small grey text) that reads
|
||||
# as metadata rather than content, so reasoning summaries default to it
|
||||
# here instead of the fenced code block used elsewhere.
|
||||
"discord": {**_TIER_HIGH, "reasoning_style": "subtext"},
|
||||
|
||||
# Tier 2 — edit support, often customer/workspace channels
|
||||
# Slack: tool_progress off by default — Bolt posts cannot be edited like CLI;
|
||||
|
|
@ -242,6 +251,9 @@ def _normalise(setting: str, value: Any) -> Any:
|
|||
if setting == "tool_progress_grouping":
|
||||
val = str(value).lower()
|
||||
return val if val in ("accumulate", "separate") else "accumulate"
|
||||
if setting == "reasoning_style":
|
||||
val = str(value).lower()
|
||||
return val if val in ("code", "blockquote", "subtext") else "code"
|
||||
if setting == "tool_preview_length":
|
||||
try:
|
||||
return int(value)
|
||||
|
|
|
|||
|
|
@ -9733,7 +9733,31 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
display_reasoning += f"\n_... ({len(lines) - 15} more lines)_"
|
||||
else:
|
||||
display_reasoning = last_reasoning.strip()
|
||||
response = f"💭 **Reasoning:**\n```\n{display_reasoning}\n```\n\n{response}"
|
||||
# Render style is per-platform: Discord defaults to "-# "
|
||||
# subtext (native small grey metadata text); other
|
||||
# platforms keep the fenced code block.
|
||||
try:
|
||||
from gateway.display_config import resolve_display_setting
|
||||
_reasoning_style = resolve_display_setting(
|
||||
_load_gateway_config(),
|
||||
_platform_config_key(source.platform),
|
||||
"reasoning_style",
|
||||
"code",
|
||||
)
|
||||
except Exception:
|
||||
_reasoning_style = "code"
|
||||
if _reasoning_style == "subtext":
|
||||
_quoted = "\n".join(
|
||||
f"-# {ln}" if ln else "-#" for ln in display_reasoning.splitlines()
|
||||
)
|
||||
response = f"-# 💭 Reasoning\n{_quoted}\n\n{response}"
|
||||
elif _reasoning_style == "blockquote":
|
||||
_quoted = "\n".join(
|
||||
f"> {ln}" if ln else ">" for ln in display_reasoning.splitlines()
|
||||
)
|
||||
response = f"> 💭 **Reasoning:**\n{_quoted}\n\n{response}"
|
||||
else:
|
||||
response = f"💭 **Reasoning:**\n```\n{display_reasoning}\n```\n\n{response}"
|
||||
|
||||
# Runtime-metadata footer — only on the FINAL message of the turn.
|
||||
# Off by default (display.runtime_footer.enabled=false). When
|
||||
|
|
|
|||
|
|
@ -1667,6 +1667,12 @@ DEFAULT_CONFIG = {
|
|||
# applies where tool_progress is already enabled. Per-platform override
|
||||
# via display.platforms.<platform>.tool_progress_grouping.
|
||||
"tool_progress_grouping": "accumulate",
|
||||
# How a reasoning/thinking summary renders when show_reasoning is on.
|
||||
# "code" (default) = 💭 fenced code block; "blockquote" = "> " lines;
|
||||
# "subtext" = "-# " lines (Discord small grey metadata text). Discord
|
||||
# defaults to "subtext"; override per-platform via
|
||||
# display.platforms.<platform>.reasoning_style.
|
||||
"reasoning_style": "code",
|
||||
# Auto-delete system-notice replies (e.g. "✨ New session started!",
|
||||
# "♻ Restarting gateway…", "⚡ Stopped…") after N seconds on platforms
|
||||
# that support message deletion (currently Telegram; other platforms
|
||||
|
|
|
|||
|
|
@ -510,3 +510,48 @@ class TestToolProgressGrouping:
|
|||
resolve_display_setting(config, "telegram", "tool_progress_grouping")
|
||||
== "separate"
|
||||
)
|
||||
|
||||
|
||||
class TestReasoningStyle:
|
||||
"""Per-platform reasoning render style (code | blockquote | subtext)."""
|
||||
|
||||
def test_discord_defaults_to_subtext(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
assert resolve_display_setting({}, "discord", "reasoning_style") == "subtext"
|
||||
|
||||
def test_other_platforms_default_to_code(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
for plat in ("telegram", "slack", "matrix", "api_server"):
|
||||
assert (
|
||||
resolve_display_setting({}, plat, "reasoning_style") == "code"
|
||||
), plat
|
||||
|
||||
def test_platform_override_wins(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
config = {"display": {"platforms": {"discord": {"reasoning_style": "blockquote"}}}}
|
||||
assert (
|
||||
resolve_display_setting(config, "discord", "reasoning_style") == "blockquote"
|
||||
)
|
||||
|
||||
def test_global_override(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
config = {"display": {"reasoning_style": "subtext"}}
|
||||
assert (
|
||||
resolve_display_setting(config, "telegram", "reasoning_style") == "subtext"
|
||||
)
|
||||
|
||||
def test_invalid_value_falls_back_to_code(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
config = {"display": {"reasoning_style": "bogus"}}
|
||||
assert resolve_display_setting(config, "telegram", "reasoning_style") == "code"
|
||||
|
||||
def test_case_insensitive(self):
|
||||
from gateway.display_config import resolve_display_setting
|
||||
|
||||
config = {"display": {"reasoning_style": "SUBTEXT"}}
|
||||
assert resolve_display_setting(config, "telegram", "reasoning_style") == "subtext"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue