Add Desktop-managed Computer Use bridge - #61507
DanBennettUK wants to merge 5 commits into
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Comment (high surface area)
Overview
- Multiple files, +2396/-41 lines
- Adds Desktop-managed Computer Use bridge
- Substantial new feature
Note
- Large diff — recommend human deep-dive
- Security surface area: computer use bridge handles external commands
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing the real remote-tool-locality gap; current main still runs Computer Use on the backend host (tools/computer_use/tool.py:151-154).
Problems
tools/computer_use/desktop_bridge.py:50-54,75-80,146-178maintains one global Desktop WebSocket and replaces it on a later connection.tools/computer_use/tool.py:151-169then selects that connected bridge globally. The bridge route authenticates a connector but does not retain its principal, although ticket consumption has one (hermes_cli/dashboard_auth/ws_tickets.py:62-99). This can route another session's Computer Use calls to the newest Desktop.website/docs/reference/environment-variables.md:517-521makes non-secret behavior user-configurable through newHERMES_*variables, contrary to the config.yaml policy.
Suggested changes
- Scope bridge registration and lookup to the authenticated principal plus the agent/session/profile context; reject unmatched calls. Add a two-principal isolation test.
- Move backend mode, bridge URL, timeout, and enablement to config/UI; keep only the bearer token in
.env.
Automated hermes-sweeper review.
c4d04f6 to
d968047
Compare
|
Re-scoped this PR to the two review concerns and updated it against current
I deliberately removed the broader public-OAuth/session policy, generic command-policy work, and unrelated primary-startup lifecycle hardening from this revision. Those are preserved separately for follow-up review rather than smuggled into this feature fix. Validation: targeted Python bridge/auth/propagation suites, Electron config/lifecycle suites, ESLint/Prettier, focused TS/esbuild checks, and |
|
Now with the HUD feature, this PR is a must. |
|
+1 — this is exactly the missing piece for the common “Hermes Desktop on a Mac, agent brain on a remote Docker/NAS backend” setup. Live repro (today, without this PR)
Why this PR mattersA Desktop-managed reverse bridge (loopback sidecar + outbound WS to remote backend) is the right shape: keep TCC/cua-driver on the Mac where the GUI lives, keep the agent runtime on the always-on host. Manual full-Hermes-on-Mac or SSH hacks shouldn’t be required for the default remote-Desktop topology. Happy to re-test against a build that includes this once it lands. |
|
Leaving this open — the gap it identifies is real and now confirmed at line level, but the way in has changed. Two PRs went up today that move it: #90380 adds a #90374 does the part that shouldn't wait for a bridge at all: on a remote gateway the agent is now told that the window it just read is on a machine it cannot click, and the Computer Use settings card names which machine it is describing. That is the reported symptom ("computer_use never appears, enabling it and restarting doesn't help") turned into an explanation instead of silence. What still needs an answer before the bridge lands, and it is the one teknium raised directly rather than the sweeper: the lite client. The desktop app ships in a build with no agent venv, and a provider that spawns a local Python sidecar has nothing to spawn there. A provider's The second sweeper finding is a straight fix under #90380: backend mode, bridge URL, timeout, and enablement move to Rebasing 5k lines onto a branch that far ahead is real work, so if you would rather hand it off than carry it, say so and I will re-land it as a provider with your authorship preserved. Either way the core edits should drop out of the diff. |
|
Correcting my last comment: I offered you the choice of carrying this or handing it off. Scratch that — we're taking it forward ourselves on top of #90380, rebuilt as a provider. Your authorship stays on the commits. Nothing for you to do, and no reflection on the work — the locality gap you identified is real and the line-level confirmation in #90374 came straight out of this PR. It's that the rebase, the principal scoping, the config move, and the lite-client question are ours to answer rather than yours to chase across a branch this far behind. I'll link the follow-up here when it's up. |
|
Carried this forward myself rather than asking you to rebase — the branch was far enough from current It's now #90423, stacked on the provider seam in #90380. Your commits are in it with authorship intact; the docs, the bridge backend, the reverse-WebSocket broker, and the principal/profile scoping are all yours. Two things changed in the carry, both because the original was global where the product isn't:
Also added: a Desktop with no local agent runtime now says the bridge can't run here instead of leaving the toggle looking on. Closing this one in favor of #90423 — thanks for building it. |
Summary
computer_usewhen the bridge is connected.Safety / behaviour
127.0.0.1by default.Verification
Server/local checks:
python -m py_compile tools/computer_use/desktop_bridge.py tools/computer_use/bridge.py tools/computer_use/tool.py hermes_cli/web_server.py tui_gateway/server.py tests/test_web_server.py tests/computer_use/test_desktop_bridge_backend.pypython -m pytest tests/computer_use/test_bridge_backend.py tests/computer_use/test_desktop_bridge_backend.py tests/tools/test_computer_use.py tests/test_web_server.py -o 'addopts=' -q→200 passedpython -m ruff check tests/test_web_server.py tests/computer_use/test_desktop_bridge_backend.py tools/computer_use/desktop_bridge.py tools/computer_use/bridge.py tools/computer_use/tool.py hermes_cli/web_server.py tui_gateway/server.py→ passgit diff --check→ passcd apps/desktop && npm run typecheck -- --noEmit→ passcd apps/desktop && npx tsx --test electron/connection-config.test.ts→53 passedcd apps/desktop && npm run lint→0 errorswith existing warningscd apps/desktop && npm run build→ passMac / live E2E:
/tmp/hermes-desktop-remote-tool-localityonDBENNETT-O3.5 passed.127.0.0.1:9139withHERMES_COMPUTER_USE_BACKEND=desktop-bridge.HERMES_HOME/ user-data./api/tools/computer-use/statuson the remote backend reported the local Mac path:platform: darwinready: truebridge.connected: truecua-driver 0.5.1true9139backend, Mac Electron process, bridge sidecar, and SSH tunnel; normal9119returned HTTP200on both server and Mac.Notes
The live E2E found and fixed an event-loop deadlock in the status route: FastAPI status handlers must use the async broker request path, while off-loop tool calls keep the synchronous path.