mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 16:18:55 +00:00
feat(agent): add display.show_commentary toggle for Codex commentary channel
Commentary delivery is on by default; users who find the extra mid-turn narration noisy can set display.show_commentary: false to restore the previous behavior (commentary routed to the reasoning channel, visible only with show_reasoning). - hermes_cli/config.py: display.show_commentary default true - agent/agent_init.py: wire config -> agent.show_commentary - run_agent.py: gate structured commentary extraction on the flag - agent/codex_runtime.py: gate live-stream commentary callback (falls back to legacy reasoning-channel routing when off) - docs + 2 tests (interim path off, live stream fallback) Also adds AUTHOR_MAP entries for davidrobertson and 100yenadmin.
This commit is contained in:
parent
7041c56cdf
commit
779019ef7d
7 changed files with 100 additions and 1 deletions
|
|
@ -1359,6 +1359,19 @@ def init_agent(
|
|||
except Exception:
|
||||
_agent_cfg = {}
|
||||
|
||||
# Codex commentary visibility (display.show_commentary, default true).
|
||||
# When true, completed Codex phase=commentary messages are delivered as
|
||||
# visible mid-turn updates through the interim message path. When false,
|
||||
# commentary falls back to the reasoning channel (visible only with
|
||||
# show_reasoning enabled).
|
||||
agent.show_commentary = True
|
||||
try:
|
||||
_display_section = _agent_cfg.get("display", {})
|
||||
if isinstance(_display_section, dict):
|
||||
agent.show_commentary = bool(_display_section.get("show_commentary", True))
|
||||
except Exception:
|
||||
agent.show_commentary = True
|
||||
|
||||
# LM Studio can either be explicitly preloaded through LM Studio's
|
||||
# management API (the historical Hermes behavior) or left to LM Studio's
|
||||
# just-in-time / Auto-Evict chat-completions path. Keep the default
|
||||
|
|
|
|||
|
|
@ -940,7 +940,10 @@ def run_codex_stream(agent, api_kwargs: dict, client: Any = None, on_first_delta
|
|||
on_reasoning_delta=_on_reasoning_delta,
|
||||
on_commentary_message=(
|
||||
_on_commentary_message
|
||||
if getattr(agent, "interim_assistant_callback", None) is not None
|
||||
if (
|
||||
getattr(agent, "interim_assistant_callback", None) is not None
|
||||
and getattr(agent, "show_commentary", True)
|
||||
)
|
||||
else None
|
||||
),
|
||||
on_first_delta=on_first_delta,
|
||||
|
|
|
|||
|
|
@ -1906,6 +1906,12 @@ DEFAULT_CONFIG = {
|
|||
"last_lines": 2,
|
||||
},
|
||||
"interim_assistant_messages": True, # Gateway: show natural mid-turn assistant status messages
|
||||
# Codex Responses models narrate progress in a dedicated commentary
|
||||
# channel. When true (default), completed commentary messages are
|
||||
# delivered as visible mid-turn updates via the interim message path.
|
||||
# When false, commentary falls back to the reasoning channel and is
|
||||
# only visible when show_reasoning is enabled.
|
||||
"show_commentary": True,
|
||||
"tool_progress_command": False, # Enable /verbose command in messaging gateway
|
||||
"tool_progress_overrides": {}, # DEPRECATED — use display.platforms instead
|
||||
"tool_preview_length": 0, # Max chars for tool call previews (0 = no limit, show full paths/commands)
|
||||
|
|
|
|||
|
|
@ -4766,6 +4766,10 @@ class AIAgent:
|
|||
commentary through the interim assistant callback before tool calls run.
|
||||
``phase=analysis`` remains hidden because it is provider scratchpad.
|
||||
"""
|
||||
if not getattr(self, "show_commentary", True):
|
||||
# display.show_commentary=false — commentary stays on the
|
||||
# reasoning channel (pre-commentary-channel behavior).
|
||||
return []
|
||||
items = assistant_msg.get("codex_message_items")
|
||||
if not isinstance(items, list):
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -371,6 +371,8 @@ AUTHOR_MAP = {
|
|||
"rasitakyol@hotmail.com": "rasitakyol",
|
||||
"thatgfsj@gmail.com": "Thatgfsj",
|
||||
"141703117+seagpt@users.noreply.github.com": "seagpt",
|
||||
"dr@nevernet.com": "davidrobertson",
|
||||
"eva@100yen.org": "100yenadmin",
|
||||
"yakimenkoleksander228@gmail.com": "doxe0x",
|
||||
"a54983334@163.com": "Code-suphub",
|
||||
"78542984+Code-suphub@users.noreply.github.com": "Code-suphub",
|
||||
|
|
|
|||
|
|
@ -2421,6 +2421,74 @@ def test_interim_commentary_redacts_secrets_from_codex_commentary_items(monkeypa
|
|||
assert "Using credential" in observed[0]
|
||||
|
||||
|
||||
def test_interim_commentary_respects_show_commentary_off(monkeypatch):
|
||||
"""display.show_commentary=false keeps commentary off the interim path."""
|
||||
agent = _build_agent(monkeypatch)
|
||||
agent.show_commentary = False
|
||||
observed = []
|
||||
agent.interim_assistant_callback = (
|
||||
lambda text, *, already_streamed=False: observed.append(text)
|
||||
)
|
||||
|
||||
agent._emit_interim_assistant_message({
|
||||
"role": "assistant",
|
||||
"content": "",
|
||||
"codex_message_items": [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "assistant",
|
||||
"phase": "commentary",
|
||||
"content": [
|
||||
{"type": "output_text", "text": "I'll inspect the repo first."}
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
assert observed == []
|
||||
|
||||
|
||||
def test_run_codex_stream_show_commentary_off_falls_back_to_reasoning(monkeypatch):
|
||||
"""With show_commentary=false the live stream keeps the legacy behavior:
|
||||
commentary deltas flow to the reasoning channel and the interim callback
|
||||
stays silent."""
|
||||
agent = _build_agent(monkeypatch)
|
||||
agent.show_commentary = False
|
||||
delivered = []
|
||||
reasoning_streamed = []
|
||||
agent.interim_assistant_callback = (
|
||||
lambda text, *, already_streamed=False: delivered.append(text)
|
||||
)
|
||||
agent.reasoning_callback = reasoning_streamed.append
|
||||
commentary_item = SimpleNamespace(
|
||||
type="message",
|
||||
phase="commentary",
|
||||
status="completed",
|
||||
content=[SimpleNamespace(type="output_text", text="I'll inspect the repo first.")],
|
||||
)
|
||||
|
||||
def _fake_create(**kwargs):
|
||||
return _FakeCreateStream([
|
||||
SimpleNamespace(
|
||||
type="response.output_item.added",
|
||||
item=SimpleNamespace(type="message", phase="commentary"),
|
||||
),
|
||||
SimpleNamespace(type="response.output_text.delta", delta="I'll inspect the repo first."),
|
||||
SimpleNamespace(type="response.output_item.done", item=commentary_item),
|
||||
SimpleNamespace(
|
||||
type="response.completed",
|
||||
response=SimpleNamespace(status="completed"),
|
||||
),
|
||||
])
|
||||
|
||||
agent.client = SimpleNamespace(responses=SimpleNamespace(create=_fake_create))
|
||||
|
||||
agent._run_codex_stream(_codex_request_kwargs())
|
||||
|
||||
assert delivered == []
|
||||
assert reasoning_streamed == ["I'll inspect the repo first."]
|
||||
|
||||
|
||||
def test_interim_commentary_deduplicates_identical_items_in_one_response(monkeypatch):
|
||||
agent = _build_agent(monkeypatch)
|
||||
observed = []
|
||||
|
|
|
|||
|
|
@ -1474,6 +1474,7 @@ display:
|
|||
platforms: {} # Per-platform display overrides (see below)
|
||||
tool_progress_overrides: {} # DEPRECATED — use display.platforms instead
|
||||
interim_assistant_messages: true # Gateway: send natural mid-turn assistant updates as separate messages
|
||||
show_commentary: true # Codex models: deliver commentary-channel progress narration as visible mid-turn updates
|
||||
skin: default # Built-in or custom CLI skin (see user-guide/features/skins)
|
||||
personality: "kawaii" # Legacy cosmetic field still surfaced in some summaries
|
||||
compact: false # Compact output mode (less whitespace)
|
||||
|
|
@ -1590,6 +1591,8 @@ Signal is listed as a valid platform key because the setting can be saved per pl
|
|||
|
||||
`interim_assistant_messages` is gateway-only. When enabled, Hermes sends completed mid-turn assistant updates as separate chat messages. This is independent from `tool_progress` and does not require gateway streaming.
|
||||
|
||||
`show_commentary` (default `true`) controls Codex Responses models' commentary channel — the polished progress narration these models produce alongside their private reasoning. When enabled, each completed commentary message is delivered as a visible mid-turn update (on the gateway this also requires `interim_assistant_messages`). Set it to `false` if the extra narration annoys you: commentary then falls back to the reasoning channel and is only shown when `show_reasoning` is enabled.
|
||||
|
||||
## Privacy
|
||||
|
||||
```yaml
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue