Skip to content

feat(tui): add opt-in remote bridge listener - #35993

Open
lsaether wants to merge 4 commits into
NousResearch:mainfrom
lsaether:feat/tui-remote-bridge
Open

lsaether wants to merge 4 commits into
NousResearch:mainfrom
lsaether:feat/tui-remote-bridge

Conversation

@lsaether

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds an opt-in remote TUI bridge listener so a separate client can attach to live TUI sessions without taking ownership away from the local terminal UI.

The bridge is intentionally conservative:

  • disabled by default
  • loopback-only by default
  • requires an explicit token for non-loopback binds
  • validates Host and Origin for remote connections
  • scopes the bridge RPC surface to a live-control allowlist instead of changing the shared dashboard /api/ws behavior

It also handles the TUI-side live-session edge cases needed for mobile/remote control:

  • hydrates reconnecting bridge clients from a bounded display journal instead of reduced canonical history
  • mirrors live gateway events to bridge transports with copy-on-write fanout
  • handles peer prompt submission during an active local turn by archiving the live turn before appending the remote prompt

Related Issue

No dedicated tracking issue yet.

Related but separate open PRs:

Type of Change

  • Bug fix
  • New feature
  • Security hardening
  • Documentation update
  • Tests
  • Refactor
  • New skill

Changes Made

  • tui_gateway/remote_bridge.py: add the optional remote bridge listener, token/host/origin validation, and bridge method allowlist wiring.
  • tui_gateway/ws.py: make RPC method allowlisting caller-scoped so bridge policy does not regress dashboard /api/ws clients.
  • tui_gateway/server.py: add remote transport fanout, bridge lifecycle handling, display-journal reconnect hydration, and peer prompt handling during active turns.
  • tui_gateway/entry.py: start the bridge listener from TUI gateway config when enabled.
  • hermes_cli/config.py and cli-config.yaml.example: document remote bridge config/env defaults.
  • tools/approval.py: preserve bridge/client context through approval flows.
  • ui-tui/src/app/* and ui-tui/src/gatewayTypes.ts: handle bridge gateway events and peer prompt/turn-boundary behavior in the TUI client.
  • tests/tui_gateway/test_remote_bridge.py, tests/test_tui_gateway_server.py, and ui-tui/src/__tests__/createGatewayEventHandler.test.ts: add backend and frontend regression coverage.

How to Test

Focused checks run from ~/Code/hermes-tui-remote-bridge:

  1. Python compile check:

    .venv/bin/python -m py_compile tui_gateway/remote_bridge.py tui_gateway/ws.py tui_gateway/entry.py tui_gateway/server.py tests/tui_gateway/test_remote_bridge.py
  2. Config parse check:

    .venv/bin/python - <<'PY'
    import yaml
    with open('cli-config.yaml.example', 'r', encoding='utf-8') as f:
        yaml.safe_load(f)
    print('cli-config.yaml.example parses')
    PY
  3. Focused backend tests:

    scripts/run_tests.sh tests/tui_gateway/test_remote_bridge.py tests/test_tui_gateway_server.py

    Result: 211 tests passed, 0 failed.

  4. Focused TUI tests:

    npm --prefix ui-tui test -- createGatewayEventHandler

    Result: 53 tests passed.

  5. Windows-footgun check:

    .venv/bin/python scripts/check-windows-footguns.py --diff origin/main

    Result: No Windows footguns found.

  6. Whitespace check:

    git diff --check origin/main...HEAD

    Result: clean.

Full-suite note: I also tried scripts/run_tests.sh across the whole repository. It does not currently complete in this local checkout because unrelated files fail outside this PR's diff, mostly from missing optional/local dependencies (acp, websockets, ptyprocess) and local environment-sensitive tests. None of the full-suite failing files intersect this PR's changed file list. The focused backend/frontend suites above cover the changed TUI gateway and bridge paths.

Checklist

Code

  • I've read the Contributing Guide
  • My commit message follows Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this feature
  • I've run pytest tests/ -q and all tests pass — full suite attempted locally but blocked by unrelated environment/dependency failures; see note above
  • I've added tests for my changes
  • I've tested on my platform: Linux / Arch worktree environment

Documentation & Housekeeping

  • I've updated relevant documentation/config examples
  • I've updated cli-config.yaml.example for the new config keys
  • CONTRIBUTING.md / AGENTS.md updates are N/A
  • I've considered cross-platform impact; Windows-footgun check is clean
  • Tool descriptions/schemas updates are N/A

Screenshots / Logs

No screenshots; this is backend bridge plumbing plus TUI event handling. Focused command output is summarized in the test plan above.

Add a disabled-by-default remote TUI bridge that can mirror and control live TUI sessions from a separate client without stealing the local TUI transport.

The bridge uses explicit config/env enablement, loopback-first defaults, token validation for non-loopback binds, host/origin checks, and a bridge-scoped RPC allowlist.

Also add reconnect hydration from the display journal, active-turn peer prompt handling, and regression coverage across backend gateway and TUI event handling paths.
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/config Config system, migrations, profiles labels May 31, 2026
lsaether added 3 commits May 31, 2026 13:16
Refresh PR NousResearch#35993 without rewriting branch history. Resolves current main conflicts while preserving the remote bridge behavior and mobile-control additions.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the substantial opt-in bridge work. It needs a targeted salvage onto current main rather than a direct application.

Problems

  • The PR’s prompt.submit busy path returns 4009 unless its new interrupt option is set. Current main routes busy submits through _handle_busy_submit at tui_gateway/server.py:8447-8452 specifically to avoid dropping mid-turn prompts. The remote peer flow must be composed with that current path.
  • tui_gateway/remote_bridge.py:163-178 and cli-config.yaml.example:916-921 make the enable flag, host, port, path, and origins public HERMES_* overrides. AGENTS.md:102-107 requires those non-secret behavioral settings to live in config.yaml.

Suggested changes

  • Preserve _handle_busy_submit semantics and add peer-fanout coverage for its queued/default busy path.
  • Remove public non-secret environment overrides; keep bridge behavior in tui_remote_bridge config, with only credential handling separated as appropriate.

Automated hermes-sweeper review.

node = {}

enabled = _cfg_bool(node, "enabled", False)
env_enabled = (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This introduces public HERMES_* controls for a feature flag and behavioral settings (host, port, path, origins). AGENTS.md:102-107 requires those to be configured through config.yaml; keep the direct environment mechanism only for credentials or an internal child-process handoff.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform 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 sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants