mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-19 15:18:03 +00:00
feat(computer-use): surface macOS permission preflight in the desktop
Computer Use already worked through the desktop backend (the cua-driver
toolset enables + installs via Settings -> Skills & Tools), but there was
no in-app way to see or grant the two macOS permissions it needs, so "give
a model my Mac" was tribal knowledge.
The grants attach to cua-driver's OWN TCC identity (com.trycua.driver /
the installed CuaDriver.app), not Hermes -- so no app entitlement is
involved. cua-driver 0.5+ exposes `permissions status/grant`, which we wrap:
- tools/computer_use/permissions.py: thin client over the two subcommands
- hermes computer-use permissions {status,grant}: CLI parity
- GET /api/tools/computer-use/status, POST .../permissions/grant: desktop REST
- ComputerUsePanel: live Accessibility + Screen Recording state with a
Grant button (dialog attributed to CuaDriver), shown in the expanded
Computer Use toolset row. Binary install stays in the existing provider
post-setup runner.
Follow-ups: i18n the card copy; a "Stop driver" control (cua-driver stop)
for the runaway-`serve` case.
This commit is contained in:
parent
c080b2dc3e
commit
0223ea5f59
7 changed files with 505 additions and 0 deletions
|
|
@ -8349,6 +8349,7 @@ async def install_mcp_catalog_entry(body: MCPCatalogInstall, profile: Optional[s
|
|||
|
||||
# Register the mcp-install action log so /api/actions/mcp-install/status works.
|
||||
_ACTION_LOG_FILES.setdefault("mcp-install", "action-mcp-install.log")
|
||||
_ACTION_LOG_FILES.setdefault("computer-use-grant", "action-computer-use-grant.log")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -10671,6 +10672,61 @@ async def run_toolset_post_setup(
|
|||
return {"ok": True, "pid": proc.pid, "name": "tools-post-setup", "key": body.key}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Computer Use (cua-driver) — install + macOS permission state
|
||||
#
|
||||
# Computer Use drives the Mac through cua-driver, whose Accessibility +
|
||||
# Screen Recording grants attach to cua-driver's OWN TCC identity
|
||||
# (com.trycua.driver / the installed CuaDriver.app) — not the Hermes desktop
|
||||
# app or this server. The desktop's Computer Use card reflects that state and
|
||||
# triggers a grant via the same `cua-driver permissions grant` flow the CLI
|
||||
# uses, so no Hermes-side entitlement is involved.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@app.get("/api/tools/computer-use/status")
|
||||
async def get_computer_use_status(profile: Optional[str] = None):
|
||||
"""Report cua-driver install + macOS permission state for the desktop card.
|
||||
|
||||
See ``tools.computer_use.permissions.permissions_status`` for the payload
|
||||
shape. Read-only and fast (shells ``cua-driver permissions status``).
|
||||
"""
|
||||
from tools.computer_use.permissions import permissions_status
|
||||
|
||||
with _profile_scope(profile):
|
||||
return permissions_status()
|
||||
|
||||
|
||||
@app.post("/api/tools/computer-use/permissions/grant")
|
||||
async def grant_computer_use_permissions(profile: Optional[str] = None):
|
||||
"""Spawn ``hermes computer-use permissions grant`` as a background action.
|
||||
|
||||
``cua-driver permissions grant`` launches CuaDriver via LaunchServices so
|
||||
the macOS TCC dialog is attributed to com.trycua.driver, then waits for
|
||||
the user to approve. The frontend polls ``GET /api/actions/computer-use-
|
||||
grant/status`` for progress and re-reads ``/status`` once it exits.
|
||||
"""
|
||||
if sys.platform != "darwin":
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Computer Use permissions are managed on macOS only.",
|
||||
)
|
||||
try:
|
||||
proc = _spawn_hermes_action(
|
||||
_profile_cli_args(profile)
|
||||
+ ["computer-use", "permissions", "grant"],
|
||||
"computer-use-grant",
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as exc:
|
||||
_log.exception("Failed to spawn computer-use permissions grant")
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"Failed to request permissions: {exc}"
|
||||
)
|
||||
return {"ok": True, "pid": proc.pid, "name": "computer-use-grant"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Raw YAML config endpoint
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue