Skip to content

feat(desktop): let the agent drive the shell — preview pane + pane focus - #69519

Merged
OutThisLife merged 2 commits into
mainfrom
bb/desktop-preview-open
Jul 22, 2026
Merged

feat(desktop): let the agent drive the shell — preview pane + pane focus#69519
OutThisLife merged 2 commits into
mainfrom
bb/desktop-preview-open

Conversation

@OutThisLife

@OutThisLife OutThisLife commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Why

On Hermes Desktop the agent could generate UI (TUI widgets, desktop plugins, HTML → preview webview) but couldn't drive the shell around it. The Preview pane only opened when the user clicked; the agent had no way to reveal panes on request. So "open cnn.com in the preview pane" or "show me the terminal" did nothing.

What

Two desktop-gated tools on a shared event bridge — same idiom as read_terminal / close_terminal.

  • tools/desktop_ui.py — one gateway-injected emitter both tools share. Routes by HERMES_UI_SESSION_ID so events land on the window that owns the turn. None off-desktop → tools report "desktop only".
  • open_preview(url[, label])preview.open. Opens a URL / localhost / file in the preview pane. Bare domains + loopback are coaxed into fetchable URLs (www.cnn.comhttps://…, localhost:3000http://…); paths/schemes pass through to the renderer's normalizer. Handled in usePreviewRouting.
  • focus_pane(chat|files|terminal|review|sessions)pane.reveal. The desktop runs each pane's own reveal path (revealDesktopPane table) — some are toggle-bound, so a revealed pane matches a user-driven open. Handled in gateway-event.ts.

Both are check_fn on HERMES_DESKTOP (zero model-tool footprint on CLI/messaging), listed in _HERMES_CORE_TOOLS beside the other GUI affordances.

Offer, don't hijack

Both open only for the active session — a background turn never moves the user's focus or pops a pane (desktop AGENTS.md). Legit here because it's an explicit user request the agent is fulfilling, not a background side effect.

Footprint / deliberate omissions

Highest rung on the ladder: service-gated tools, not always-on core tools, and one shared bridge rather than a per-tool sink.

Not adding run_slash (agent firing slash commands): /model, /new, /clear mid-turn fight prompt-cache + conversation invariants. open_file is subsumed by open_preview (it takes a path).

Tests

  • Python: test_desktop_ui.py (routing/availability), test_open_preview_tool.py, test_focus_pane_tool.py — gating, validation, normalization, emit payloads, failure reporting.
  • Vitest: pane-focus.test.ts (each pane → its reveal path; unknown → no-op), use-preview-routing.test.tsx (active opens; background ignored).

Python + vitest green; desktop typecheck + eslint clean; core-tool-list regression suites unchanged.

Note: needs a desktop app rebuild to pick up the new renderer handlers.

Add a desktop-gated open_preview tool so 'open cnn.com in the preview
pane' works. The tool (check_fn on HERMES_DESKTOP, zero footprint
elsewhere) emits a preview.open event through a gateway-injected emitter,
mirroring the close_terminal -> terminal.close bridge. The desktop
handles it in usePreviewRouting, normalizing the target and opening the
pane for the active session only -- a background turn never hijacks it.

Bare domains and localhost are coaxed into fetchable URLs (www.cnn.com ->
https://, localhost:3000 -> http://); file paths and schemes pass through
to the renderer's normalizer.
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

running on 70ba3c4

CI timings

CI timings · View job

Wall time 7m38s vs 8m29s (-10.0%). 3 job(s) slower, 15 faster, 2 unchanged.

  • OSV scan / Scan lockfiles / osv-scan: -81.0s
  • OSV scan / Emit review status: -37.0s
  • Python tests / Run tests slice 5/8: -35.0s
  • Build&Test Docker image / build (arm64, ubuntu-24.04-arm, linux/arm64, type=gha,scope=docker-arm64, type=gha,mode=max,scope...: -25.0s
  • Python tests / Run tests slice 3/8: +21.0s

Extract the open_preview emitter into a shared tools/desktop_ui bridge
(one gateway-injected sink, routed by HERMES_UI_SESSION_ID) and add a
second desktop-gated tool on top of it:

- focus_pane(chat|files|terminal|review|sessions) -> pane.reveal event.
  The desktop runs each pane's own reveal path (revealDesktopPane table)
  and only acts on the active window -- a background turn never moves the
  user's focus (desktop AGENTS.md: offer, don't hijack).

open_preview now emits through the same bridge. Both tools are check_fn
on HERMES_DESKTOP (zero footprint elsewhere), sitting beside
read_terminal/close_terminal in _HERMES_CORE_TOOLS.

Deliberately not adding run_slash: letting the agent fire slash commands
mid-turn (/model, /new, /clear) fights prompt-cache + conversation
invariants.
@OutThisLife OutThisLife changed the title feat(desktop): let the agent open the preview pane feat(desktop): let the agent drive the shell — preview pane + pane focus Jul 22, 2026
@OutThisLife
OutThisLife enabled auto-merge July 22, 2026 17:18
@OutThisLife
OutThisLife merged commit 4204e6d into main Jul 22, 2026
41 checks passed
@OutThisLife
OutThisLife deleted the bb/desktop-preview-open branch July 22, 2026 17:18
@alt-glitch alt-glitch added type/feature New feature or request comp/desktop Electron desktop app (apps/desktop/*) comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have labels Jul 22, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…eview-open

feat(desktop): let the agent drive the shell — preview pane + pane focus
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…eview-open

feat(desktop): let the agent drive the shell — preview pane + pane focus
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants