Skip to content

fix: redirect interactive stderr away from TUI - #52441

Open
rumbin wants to merge 3 commits into
NousResearch:mainfrom
rumbin:fix-superset-redirect-host
Open

fix: redirect interactive stderr away from TUI#52441
rumbin wants to merge 3 commits into
NousResearch:mainfrom
rumbin:fix-superset-redirect-host

Conversation

@rumbin

@rumbin rumbin commented Jun 25, 2026

Copy link
Copy Markdown

Summary:

  • redirect interactive CLI stderr to ~/.hermes/logs/cli-stderr.log while the prompt_toolkit app is running
  • redact anything written to that side log
  • add targeted tests for stderr redirection and redaction

Why:

  • patch_stdout() only protects stdout
  • raw stderr writes from warnings, third-party SDKs, or MCP reconnect/auth chatter can still corrupt the live TUI prompt and make the session feel dead

Verification:

  • python -m pytest tests/test_hermes_logging.py -q -o 'addopts='
  • python -m py_compile cli.py hermes_logging.py tests/test_hermes_logging.py

rumbin added 2 commits June 23, 2026 08:01
Use the configured oauth.redirect_host for callback URI generation and listener binding. Add focused tests for localhost/IPv6 redirect URIs, dual-stack port selection, and SSH hint output.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard tool/mcp MCP client and OAuth area/auth Authentication, OAuth, credential pools sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Jun 25, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: this PR bundles two changes. The MCP OAuth redirect_host config + dual-stack loopback callback binding in tools/mcp_oauth.py overlaps open #21482 (same oauth.redirect_host config) and your earlier closed #29875. The stderr-redirect work (cli.py, hermes_logging.py) is the part matching the title. Reviewers may want the OAuth-redirect-host change split out to compare against #21482.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing terminal corruption and adding focused coverage. The stdio-MCP portion of the reported problem is already addressed on current main by 379b2273d: tools/mcp_tool.py:2097-2105 passes a profile-local log file as stdio_client(..., errlog=...).

Problems

  • The new redirect_stderr_to_log() context around the entire interactive app (cli.py:14475 in this PR) also hides deliberate user-facing OAuth output. tools/mcp_oauth.py:567 writes the authorization URL to sys.stderr, and tools/mcp_oauth.py:673 writes the paste fallback prompt; both would go only to the side log.
  • The changed URI construction at tools/mcp_oauth.py:744 directly interpolates ::1, yielding http://::1:<port>/callback. The added test itself expects the bracketed form http://[::1]:8771/callback; the pre-registered-client path has the same construction.

Suggested changes

  • Scope redirection to the identified non-interactive producer rather than replacing process-wide stderr during app.run().
  • Centralize URI-host formatting and use it in both OAuth metadata paths.
  • Consider splitting the redirect-host work noted in the existing #21482 discussion.

Automated hermes-sweeper review.

Comment thread cli.py
with patch_stdout():
from hermes_logging import redirect_stderr_to_log

with redirect_stderr_to_log(), patch_stdout():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This replaces sys.stderr for the full interactive session, but MCP OAuth intentionally prints its authorization URL and paste fallback to stderr (tools/mcp_oauth.py:567,673). Those user-required instructions would be silently diverted to the side log; scope the redirect to the noisy producer instead.

Comment thread tools/mcp_oauth.py
client_name = cfg.get("client_name", "Hermes Agent")
scope = cfg.get("scope")
redirect_uri = f"http://127.0.0.1:{port}/callback"
redirect_uri = f"http://{_oauth_uri_host}:{port}/callback"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the allowed ::1 host this constructs http://::1:<port>/callback, while the added test expects http://[::1]:8771/callback. Format IPv6 URI authorities with brackets here and in the pre-registered-client path.

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

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants