Skip to content

fix: eliminate execute_code progress spam on gateway platforms#1098

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-465f3702
Mar 12, 2026
Merged

fix: eliminate execute_code progress spam on gateway platforms#1098
teknium1 merged 1 commit into
mainfrom
hermes/hermes-465f3702

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Problem

On Telegram/Discord/etc., execute_code tool calls produce massive visual spam — a single message bubble fills with 17+ identical lines like:

🐍 execute_code: "import os
print("=== Current Director..."
🐍 execute_code: "import os
print("=== Current Director..."
(repeat 17 times)

This happens because of two independent issues:

Issue 1: Newlines in previews

build_tool_preview() preserves \n characters from execute_code's code argument. A preview like import os\nprint("...") renders as 2 visual lines per progress entry on messaging platforms. Other tools (terminal, web_search, etc.) never have newlines in their primary argument, so they don't exhibit this.

Issue 2: No deduplication of identical messages

In "all" mode (the default), every tool call gets a progress line — even when identical to the previous one. When models iterate with execute_code using the same boilerplate code (common pattern: import os\nprint(...)), each call produces an identical progress line. 9 calls × 2 visual lines each = 18 lines of identical spam.

Fixes

1. Collapse whitespace in build_tool_preview() (agent/display.py)

preview = " ".join(preview.split())

Newlines and tabs become spaces. Now: import os print("=== Current Dir..." — one clean line.

2. Dedup consecutive identical progress messages (gateway/run.py)

Track the last progress message. When the same message appears consecutively, collapse it with a repeat counter instead of adding a new line:

Before: 9 identical lines
After: 🐍 execute_code: "import os print("=== Cur..." (×9)

The dedup works by sending a special (__dedup__, msg, count) tuple through the progress queue. The send_progress_messages async loop updates the last line in-place and re-edits the Telegram message.

Testing

  • 3205 tests pass, 0 new failures
  • Verified preview collapsing works: import os\nprint(...)import os print(...) (single line, 0 newlines)

Root cause: two issues combined to create visual spam on Telegram/Discord:

1. build_tool_preview() preserved newlines from tool arguments. A preview
   like 'import os\nprint("...")' rendered as 2+ visual lines per
   progress entry on messaging platforms. This affected execute_code most
   (code always has newlines), but could also hit terminal, memory,
   send_message, session_search, and process tools.

2. No deduplication of identical progress messages. When models iterate
   with execute_code using the same boilerplate code (common pattern),
   each call produced an identical progress line. 9 calls x 2 visual
   lines = 18 lines of identical spam in one message bubble.

Fixes:
- Added _oneline() helper to collapse all whitespace (newlines, tabs) to
  single spaces. Applied to ALL code paths in build_tool_preview() —
  both the generic path and every early-return path that touches user
  content (memory, session_search, send_message, process).
- Added dedup in gateway progress_callback: consecutive identical messages
  are collapsed with a repeat counter, e.g. 'execute_code: ... (x9)'
  instead of 9 identical lines. The send_progress_messages async loop
  handles dedup tuples by updating the last progress_line in-place.
@teknium1 teknium1 force-pushed the hermes/hermes-465f3702 branch from 71eaf39 to 8121aef Compare March 12, 2026 22:53
@teknium1 teknium1 merged commit def7b84 into main Mar 12, 2026
1 check failed
teknium1 pushed a commit that referenced this pull request Apr 22, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (#1157)
- Orphaned Chrome processes via process-group kill on shutdown (#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (#1134)
- Idle timeout not firing (sleep future recreated each loop) (#1110)
- Navigation hanging on lifecycle events that never fire (#1059, #1092)
- CDP attach hang on Chrome 144+ (#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses #7343 (daemon socket hangs, shadow DOM) and #13793 (orphan
accumulation from force-killed sessions).
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…465f3702

fix: eliminate execute_code progress spam on gateway platforms
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (NousResearch#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (NousResearch#1157)
- Orphaned Chrome processes via process-group kill on shutdown (NousResearch#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (NousResearch#1134)
- Idle timeout not firing (sleep future recreated each loop) (NousResearch#1110)
- Navigation hanging on lifecycle events that never fire (NousResearch#1059, NousResearch#1092)
- CDP attach hang on Chrome 144+ (NousResearch#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (NousResearch#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses NousResearch#7343 (daemon socket hangs, shadow DOM) and NousResearch#13793 (orphan
accumulation from force-killed sessions).
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (NousResearch#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (NousResearch#1157)
- Orphaned Chrome processes via process-group kill on shutdown (NousResearch#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (NousResearch#1134)
- Idle timeout not firing (sleep future recreated each loop) (NousResearch#1110)
- Navigation hanging on lifecycle events that never fire (NousResearch#1059, NousResearch#1092)
- CDP attach hang on Chrome 144+ (NousResearch#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (NousResearch#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses NousResearch#7343 (daemon socket hangs, shadow DOM) and NousResearch#13793 (orphan
accumulation from force-killed sessions).
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…465f3702

fix: eliminate execute_code progress spam on gateway platforms
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (NousResearch#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (NousResearch#1157)
- Orphaned Chrome processes via process-group kill on shutdown (NousResearch#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (NousResearch#1134)
- Idle timeout not firing (sleep future recreated each loop) (NousResearch#1110)
- Navigation hanging on lifecycle events that never fire (NousResearch#1059, NousResearch#1092)
- CDP attach hang on Chrome 144+ (NousResearch#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (NousResearch#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses NousResearch#7343 (daemon socket hangs, shadow DOM) and NousResearch#13793 (orphan
accumulation from force-killed sessions).
olympus-terminal pushed a commit to olympus-terminal/hermes-agent that referenced this pull request May 16, 2026
…465f3702

fix: eliminate execute_code progress spam on gateway platforms
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (NousResearch#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (NousResearch#1157)
- Orphaned Chrome processes via process-group kill on shutdown (NousResearch#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (NousResearch#1134)
- Idle timeout not firing (sleep future recreated each loop) (NousResearch#1110)
- Navigation hanging on lifecycle events that never fire (NousResearch#1059, NousResearch#1092)
- CDP attach hang on Chrome 144+ (NousResearch#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (NousResearch#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses NousResearch#7343 (daemon socket hangs, shadow DOM) and NousResearch#13793 (orphan
accumulation from force-killed sessions).
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…465f3702

fix: eliminate execute_code progress spam on gateway platforms
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…imeout

Upgrades agent-browser from 0.13.0 to 0.26.0, picking up 13 releases of
daemon reliability fixes:

- Daemon hang on Linux from waitpid(-1) race in SIGCHLD handler (NousResearch#1098)
- Chrome killed after ~10s idle due to PR_SET_PDEATHSIG thread tracking (NousResearch#1157)
- Orphaned Chrome processes via process-group kill on shutdown (NousResearch#1137)
- Stale daemon after upgrade via .version sidecar and auto-restart (NousResearch#1134)
- Idle timeout not firing (sleep future recreated each loop) (NousResearch#1110)
- Navigation hanging on lifecycle events that never fire (NousResearch#1059, NousResearch#1092)
- CDP attach hang on Chrome 144+ (NousResearch#1133)
- Windows daemon TCP bind with Hyper-V port conflicts (NousResearch#1041)
- Shadow DOM traversal in accessibility tree snapshots
- doctor command for user self-diagnosis

Also wires AGENT_BROWSER_IDLE_TIMEOUT_MS into the browser subprocess
environment so the daemon self-terminates after our configured inactivity
timeout (default 300s). This is the daemon-side counterpart to the
Python-side inactivity reaper — the daemon kills itself and its Chrome
children when no commands arrive, preventing orphan accumulation even
when the Python process dies without running atexit handlers.

Addresses NousResearch#7343 (daemon socket hangs, shadow DOM) and NousResearch#13793 (orphan
accumulation from force-killed sessions).
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