Computer Use (legacy helper): serve machine consent from the app's acpmux

Merged
TE
9d ago
+635-1

Leo's ask this serves: "just have this sort of thing for, I guess, general onboarding of adding remote machines and whatnot and whatever, which includes, I guess, screen sharing potentially."

Before / after

Settings › Agents › Computer Use card, Status line. Before is a ready legacy helper; after is the same card when the helper refused this app as its consent host (host_unverified, e.g. an ad hoc signed dev build). Rendered from the Settings gallery (pages.settings, variants computer-use-granted and the new computer-use-host-unverified) in headless Chromium on Linux CI.

BeforeAfter
Lightcomputer use card before lightcomputer use card after light
Darkcomputer use card before darkcomputer use card after dark

No capture: no native view changes. The Swift side only adds the host_unverified state and the card strings; the one visible change is the webview Settings card above, shown from the gallery (the capture check leaves webview changes to the gallery).

What

This is the app's half of machine consent for the legacy cmux Computer Use helper (computerUse.driver = "legacy").

The helper's cmux.app build (cmux-cua's cmux-host-consent feature, manaflow-ai/cmux-cua#82, shipped here through #27393) trusts no file or environment variable for consent. It asks the cmux app on every check, and refuses everything that needs consent when no app answers.

While the helper runs, ComputerUseConsentHost holds one connection to the helper's socket:

  • It is opened the same way as the app's other helper connections: the server must be the Developer ID signed helper.
  • It starts with an authenticated machine_consent_host request. The helper admits it only with the host token and when this app's code, checked by audit token, is signed by cmux's team with a cmux app identifier.
  • The app answers each {"type":"machine_consent","id":N} from its own acpmux daemon, using the same relay and the same peer-checked daemon query the helper v2 uses (#27398).
  • It forwards each refusal for the daemon's record.

Stop condition. stop() runs when the helper stops, exits, or Computer Use turns off. It cancels the connection and any retry.

  • A lost connection is retried with Backoff (250 ms to 5 s) while the helper runs.
  • A refused attach (an older helper without the method) is logged once and not retried until the next start.

Size

About 190 changed lines, on top of #27398.

Risk

With a #27393 helper, legacy Computer Use works only while this connection is up. Tagged dev builds that are ad hoc signed fail the helper's code check, so the helper refuses every call that needs consent there. That is fail closed.

Tests

CmuxNextAppTests/ComputerUseConsentHostTests:

  • the attach line is an authenticated host request;
  • helper lines are classified correctly.

The question and answer path itself is covered by ComputerUseHelperConsentTests (#27398) and, on the helper side, by cmux-cua's host_consent tests.

🤖 Generated with Claude Code

Agent session: agent session


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Serves machine consent for the legacy Computer Use helper (computerUse.driver = "legacy") from the app's acpmux daemon. The helper's cmux-cua build trusts no file or environment variable for consent anymore — it asks this app on every check and refuses everything that needs consent when no app answers.

  • While the helper runs, ComputerUseConsentHost holds one authenticated machine_consent_host connection to the helper's socket; the helper admits it only with the host token and when the app's code (checked by audit token) is signed by cmux's team.
  • Consent questions are answered from the app's acpmux daemon via the same relay and peer-checked query as helper v2; refusals are forwarded for the daemon's record, and lines from a stopped or replaced connection are ignored.
  • Attach is recognized only on an explicit attached: true result; any other reply is not retried until the next start, while lost connections retry with Backoff (250 ms to 5 s).
  • A host_unverified refusal (an ad hoc signed dev build the helper can't verify) is logged with the helper's reason, and the Settings card says legacy Computer Use is off in this build, pointing at driver upstream or a signed build. The refusal clears when a later connection is accepted. Untrusted states fail closed.