Skip to content

refactor(gateway): extract display/resolution helpers out of run.py (first slice of #54962) - #77433

Open
andrexibiza wants to merge 4 commits into
NousResearch:mainfrom
andrexibiza:fix/gateway-display-helpers
Open

refactor(gateway): extract display/resolution helpers out of run.py (first slice of #54962)#77433
andrexibiza wants to merge 4 commits into
NousResearch:mainfrom
andrexibiza:fix/gateway-display-helpers

Conversation

@andrexibiza

@andrexibiza andrexibiza commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Related #18859 #54962 #55138 #55304

What does this PR do?

First scoped slice of the Extract Gateway Platform Routing from
gateway/run.py
refactor (#54962, #55138): extract the pure display /
resolution helpers out of the 26,800-line god-file into a focused,
tested module.

gateway/run.py is a 26,800-line god-file. This PR pulls the first
cohesive cluster — display and thread-resolution helpers — into
gateway/display_helpers.py (201 lines) with a dedicated test module
(184 lines). Net effect: run.py shrinks by 250 lines, no behavior
change (pure move + import), and the extracted helpers get direct unit
coverage they previously lacked (34 tests).

Extracted:

  • _resolve_progress_thread_id — progress/status bubble thread targeting
    (incl. the fix(gateway): respect reply_in_thread=false for Slack progress messages #18859 synthetic-thread case)
  • _telegramize_command_mentions + _TELEGRAM_COMMAND_MENTION_RE
  • _gateway_platform_value, _has_platform_display_override,
    _resolve_gateway_display_bool
  • _coerce_gateway_timestamp, _auto_continue_freshness_window,
    _float_env, _AUTO_CONTINUE_FRESHNESS_SECS_DEFAULT

Scope honesty

The issue title promises full platform-routing extraction from a 26K-line
file — that is a multi-PR effort, not a single landable diff. This PR
ships the first verifiable slice and proves the extraction pattern
(module + tests + shrink) so follow-up slices can land the same way.
gateway/run.py still contains the platform adapters and dispatch loop;
those are separate follow-up extractions.

Credit

Cherry-picked from #55304 by @Stoltemberg (authorship preserved in git
history), conflict-resolved against current main (run.py moved on; the
stall-notify timeout constant and hygiene platform constant stay in
run.py where they're used; the extracted helpers are imported at the
extraction site).

How to test

pytest tests/gateway/test_display_helpers.py -q
# 34 passed

What platforms were tested?

  • Windows 11 native: 34 passed, both files parse, imports resolve,
    git diff --check clean, attribution audit clean.

Why this matters

gateway/run.py at 26.8K lines is the largest file in the codebase;
every fix or feature in the gateway requires navigating it. This is the
first concrete step of the accepted god-file-extraction pattern
(AGENTS.md: "Refactor god-files into clean modules... even when the diff
is huge and mechanical"), and it adds real test coverage to helpers that
had none.

Part of #54962
Part of #55138 (Extract Gateway Platform Routing)

  • Refactor (no behavior change)
  • Bug fix
  • Breaking change

Checklist

Part of #78647

…lay_helpers.py

Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>

# Conflicts:
#	gateway/run.py
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Aug 3, 2026
andrexibiza added a commit to andrexibiza/hermes-agent that referenced this pull request Aug 3, 2026
… of NousResearch#54962)

Third slice of the gateway god-file unpacking: extract
build_resume_recovery_note, _build_replay_entry and the shared
_ASSISTANT_REPLAY_FIELDS whitelist into
gateway/resume_replay_helpers.py.

- Byte-identical extraction (AST-verified against origin/main): no
  behavior change
- gateway/run.py: -172 lines; helpers imported at the extraction point
  (module-attribute imports keep existing tests green)
- 43 tests pass across replay-entry, resume-pending, and message
  timestamp suites

Follow-up to NousResearch#77433 (slice 1) and NousResearch#77438 (slice 2). Progress on NousResearch#54962.

Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>
andrexibiza added a commit to andrexibiza/hermes-agent that referenced this pull request Aug 3, 2026
… 5 of NousResearch#54962)

Fifth slice of the gateway god-file unpacking: extract
_is_transient_network_error and _gateway_loop_exception_handler into
gateway/error_helpers.py.

- Byte-identical extraction (AST-verified against origin/main): the
  classifier walks the exception cause chain (NousResearch#31066/NousResearch#31110); the loop
  handler wires it into the event-loop safety net
- gateway/run.py: -78 lines; helpers imported at the extraction point
- 46 tests pass (loop exception handler + compression notices)

Follow-up to NousResearch#77433 (slice 1), NousResearch#77438 (slices 2-3), NousResearch#77450 (slice 4).
Progress on NousResearch#54962.

Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>
Two extracted functions drifted from the cherry-picked branch vs current
main and broke CI (TypeError: _resolve_progress_thread_id() got an
unexpected keyword argument 'reply_in_thread'):

- _resolve_progress_thread_id: restore the reply_in_thread kwonly param
  and the NousResearch#18859 synthetic-thread handling
- _auto_continue_freshness_window: delegate to gateway.session (the
  single source of truth) instead of reading the env var directly

All 8 extracted functions now AST-identical to origin/main. 34 tests pass.

Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>
… extraction (CI fix)

The slice-1 extraction (cherry-picked from NousResearch#55304) removed
_startup_restore_drain_timeout_secs and its default constant along with
the display helpers, but the function is still called at run.py:9927 —
NameError in test_restart_resume_pending (CI slice 2).

Restore both into gateway.display_helpers (AST-identical to
origin/main) and import them back into run.py. Verified no other
orphaned references remain (AST scan: NONE). 65 tests pass.

Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Six open PRs address the duplicated #54962/#55138 request through scoped extractions from gateway/run.py: #77376 extracts platform-routing policy, #77433 display/resolution helpers, #77438 message/config helpers, #77450 compression-status matching, #77452 resume/replay helpers, and #77455 transient-error handling. These reduce the god-file through independently testable modules, but none extracts the requested adapter-owned payload/event/serialization pipeline or introduces the proposed platform ABC.

Related pull requests

Duplicates

#54962 and #55138 are duplicate issues, with #77376 carrying the structural closes edge for #55138. No listed PRs are wholesale duplicates in the visible diffs, though #77376 and #77433 both extract _gateway_platform_value and therefore require overlap resolution.

Suggested consolidation

Keep #77376 open with its independently tested platform-routing-helper extraction as the strongest salvage path and recorded best fix for #54962/#55138/#67967; close issue #55138 as a duplicate of #54962. Keep #77433 open as the recorded best-fix display-extraction slice for #67967, but author action is required to rebase onto the chosen ordering or split out its duplicated _gateway_platform_value; keep #77438, #77450, #77452, and #77455 open only as distinct salvageable god-file slices, while tracking the still-separate adapter ABC and adapter-owned payload/event/serialization work under #54962.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I67967(["issue #67967 (closed)"])
    P77433["PR #77433 (open)"]
    P77433 -->|best fix| I67967
    class I67967 closed
    class P77433 open
    class P77433 best
    class P77433 target
    click I67967 "https://github.com/NousResearch/hermes-agent/issues/67967"
    click P77433 "https://github.com/NousResearch/hermes-agent/pull/77433"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 6 pull requests and 3 issues in this complex. Each diff was read against this issue; Assessment working set: 82 kB of PR diffs, 26 kB of issue/PR text, 11 kB of discussion (10 comments), 12 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

…ay_helpers

display_helpers.py extracted its own copy of _gateway_platform_value,
duplicating the identical helper that the platform-routing slice (NousResearch#77376)
extracts into gateway/platform_routing.py. Keep the single definition in
gateway.run and pass the caller-normalized platform value into
_resolve_gateway_display_bool instead, so the two slices do not overlap.

- remove _gateway_platform_value from gateway/display_helpers.py
- restore the definition in gateway/run.py (source of truth on main)
- _resolve_gateway_display_bool takes platform_value (normalized str)
  and require_platform_override_for as normalized platform keys
- update the show_reasoning call site and mattermost tests
- add direct tests for _resolve_gateway_display_bool
@andrexibiza

Copy link
Copy Markdown
Contributor Author

Fixed in cecc6cb — the duplicated _gateway_platform_value overlap with #77376 is resolved.

What changed

  • gateway/display_helpers.py no longer defines _gateway_platform_value — the single definition stays in gateway/run.py, so the display slice and the platform-routing slice (refactor(gateway): extract platform routing helpers from run.py #77376) do not extract the same helper into two modules.
  • _resolve_gateway_display_bool now takes platform_value (caller-normalized lowercase platform key) and require_platform_override_for as normalized platform keys, instead of re-normalizing internally.
  • Updated the show_reasoning call site in run.py and the Mattermost tests to the new signature.
  • Added direct tests for _resolve_gateway_display_bool covering the platform-only opt-in behavior (blocked without override, enabled with explicit display.platforms.<platform> override, other platforms unaffected).

Validation

  • scripts/run_tests.sh: 41 passed, 0 failed (test_display_helpers, test_mattermost, test_run_cleanup_progress, test_run_progress_topics)
  • Ruff: clean; git diff --check: clean; Windows footgun lint: clean

This resolves the overlap without a merge-order dependency on #77376: _gateway_platform_value remains in run.py until the platform-routing slice lands, so whichever merges first, the other applies cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants