From 2095f6a3de238b6d7615c3351c0f75f45ad56458 Mon Sep 17 00:00:00 2001 From: abonneth Date: Wed, 30 Sep 2026 19:32:05 +0200 Subject: [PATCH 1/2] feat(local): cua in the workstation extra, CUA_SESSION per bridge session Co-authored-by: Cursor --- pyproject.toml | 2 +- src/hai_agents_local/workstation.py | 3 ++- tests/test_local.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 28f583c..478be8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ browser = [ "hai-drivers[web]>=0.1.3", ] workstation = [ - "hai-drivers[browser-cli,desktop-cli]>=0.1.6", + "hai-drivers[browser-cli,cua-cli,desktop-cli]>=0.1.8", ] all = [ "hai-agents[browser,cli,desktop,workstation]", diff --git a/src/hai_agents_local/workstation.py b/src/hai_agents_local/workstation.py index 9fe332e..aca6579 100644 --- a/src/hai_agents_local/workstation.py +++ b/src/hai_agents_local/workstation.py @@ -1,4 +1,4 @@ -"""Local workstation bridge: the agent's shell runs on this machine and drives it through the desk and web CLIs.""" +"""Local workstation bridge: the agent's shell runs on this machine and drives it through the desk, cua and web CLIs.""" from __future__ import annotations @@ -58,6 +58,7 @@ def create_driver(self) -> ManagedCodeSandboxInterface: str(self.workspace), environment_variables={ "COORDINATE_SYSTEM": "0-1000", + "CUA_SESSION": self.session_id, "PATH": os.pathsep.join([os.path.dirname(desk), path]), }, ) diff --git a/tests/test_local.py b/tests/test_local.py index d485639..6d02de4 100644 --- a/tests/test_local.py +++ b/tests/test_local.py @@ -689,12 +689,12 @@ def test_workstation_serves_a_shell_in_its_session_folder_with_the_cli_commands( bridge._driver = bridge.create_driver() try: result, error = bridge._dispatch( - "execute", {"command": "pwd -P; echo $COORDINATE_SYSTEM; command -v desk web click"} + "execute", {"command": "pwd -P; echo $COORDINATE_SYSTEM $CUA_SESSION; command -v desk web cua click"} ) assert error is None and result["exit_code"] == 0 out = result["stdout"].split() assert out[0] == str((tmp_path / "hai" / bridge.session_id).resolve()) - assert out[1] == "0-1000" and len(out) == 5 + assert out[1:3] == ["0-1000", bridge.session_id] and len(out) == 7 finally: bridge._driver.close() From fd90088f185668ff0bbd3ce05a97737d34e22ce9 Mon Sep 17 00:00:00 2001 From: abonneth Date: Fri, 2 Oct 2026 18:36:20 +0200 Subject: [PATCH 2/2] feat(local): hai-drivers 0.1.9 (cua web) in the workstation extra Co-authored-by: Cursor --- pyproject.toml | 2 +- uv.lock | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 478be8d..3798fc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ browser = [ "hai-drivers[web]>=0.1.3", ] workstation = [ - "hai-drivers[browser-cli,cua-cli,desktop-cli]>=0.1.8", + "hai-drivers[browser-cli,cua-cli,desktop-cli]>=0.1.9", ] all = [ "hai-agents[browser,cli,desktop,workstation]", diff --git a/uv.lock b/uv.lock index f2c4d6d..fb31222 100644 --- a/uv.lock +++ b/uv.lock @@ -284,6 +284,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "cua-driver" +version = "0.30.4" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/1f/3c2e7d792e7e9141326bbea385c6505596a5114eb9ac88897ccb79730e8c/cua_driver-0.30.4-py3-none-macosx_13_0_universal2.whl", hash = "sha256:18fb6eb786eda51d027da9cf209a93b10d2f06a480ab9abfc892dc30e331fc03", size = 43518466, upload-time = "2026-09-28T21:41:42.927Z" }, + { url = "https://files.pythonhosted.org/packages/93/7c/e50cb74829066b64077f70f171c9a62757b54f04108466825944df33d6ff/cua_driver-0.30.4-py3-none-manylinux_2_31_aarch64.whl", hash = "sha256:9d7c9bb3eb6df2b52a93f711aa375bdf2c7fbc02fa925f15599b2986e7183f08", size = 32611972, upload-time = "2026-09-28T21:41:45.947Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/35d12b31be023205f8e1349aab70dd514007d6ccfc9641f21c6c18761236/cua_driver-0.30.4-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:e8cdf891b8299d5515e087167df1a628fb9104edd1fba053eaf620f5ddee864b", size = 32227932, upload-time = "2026-09-28T21:41:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ce/324d409cfe31d9b84275765996c869eb4324838b423b94111b087a868627/cua_driver-0.30.4-py3-none-win_amd64.whl", hash = "sha256:199efee24c2f0c1e6c925f712e74478a24a4605e931b7ec23181a5ec78e80f64", size = 28377116, upload-time = "2026-09-28T21:41:51.218Z" }, + { url = "https://files.pythonhosted.org/packages/76/bb/7ebea434f2a84967e3bc7f50db8831f9de3724176dc6ab6c67147d29de34/cua_driver-0.30.4-py3-none-win_arm64.whl", hash = "sha256:3de51de33d78fb354e7fef89d1697c3b783b7c953ede0fdf5bc1ba2fe951423e", size = 26558544, upload-time = "2026-09-28T21:41:53.635Z" }, +] + [[package]] name = "docstring-parser" version = "0.18.0" @@ -539,7 +551,7 @@ dependencies = [ [package.optional-dependencies] all = [ - { name = "hai-drivers", extra = ["browser-cli", "desktop", "desktop-cli", "web"] }, + { name = "hai-drivers", extra = ["browser-cli", "cua-cli", "desktop", "desktop-cli", "web"] }, { name = "python-dotenv" }, { name = "rich" }, { name = "typer" }, @@ -556,7 +568,7 @@ desktop = [ { name = "hai-drivers", extra = ["desktop"] }, ] workstation = [ - { name = "hai-drivers", extra = ["browser-cli", "desktop-cli"] }, + { name = "hai-drivers", extra = ["browser-cli", "cua-cli", "desktop-cli"] }, ] [package.dev-dependencies] @@ -572,7 +584,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "hai-agents", extras = ["browser", "cli", "desktop", "workstation"], marker = "extra == 'all'" }, - { name = "hai-drivers", extras = ["browser-cli", "desktop-cli"], marker = "extra == 'workstation'", specifier = ">=0.1.6" }, + { name = "hai-drivers", extras = ["browser-cli", "cua-cli", "desktop-cli"], marker = "extra == 'workstation'", specifier = ">=0.1.9" }, { name = "hai-drivers", extras = ["desktop"], marker = "extra == 'desktop'", specifier = ">=0.1.3" }, { name = "hai-drivers", extras = ["web"], marker = "extra == 'browser'", specifier = ">=0.1.3" }, { name = "httpx", specifier = ">=0.23.0,<0.29.0" }, @@ -596,7 +608,7 @@ dev = [ [[package]] name = "hai-drivers" -version = "0.1.6" +version = "0.1.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdownify" }, @@ -604,7 +616,7 @@ dependencies = [ { name = "pydantic" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/66/3138fa8aed6859cb01f67f6d5c96613c148d29a09aebe4dbe5be3ded2a3c/hai_drivers-0.1.6-py3-none-any.whl", hash = "sha256:d2ca6c34d441b9b7d157c8bb76944f88d2b5984d31bfd3be5aab0208e581aecd", size = 197469, upload-time = "2026-09-29T17:09:27.723Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f9/b16a8889df2034ef68f81d7b0c943a5880e4abe677abbacb8e328f9fe7d6/hai_drivers-0.1.9-py3-none-any.whl", hash = "sha256:d664a96dc362705c93b357d70dc1e16c0d093deac9f1d9c576c8c15928533f96", size = 257381, upload-time = "2026-10-02T16:33:50.527Z" }, ] [package.optional-dependencies] @@ -616,6 +628,11 @@ browser-cli = [ { name = "websockets", version = "16.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "websockets", version = "17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] +cua-cli = [ + { name = "cua-driver" }, + { name = "tyro", version = "0.8.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" }, + { name = "tyro", version = "0.9.35", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" }, +] desktop = [ { name = "pyautogui" }, { name = "pynput" },