Files
ddupont d1bc0764f6 feat: add cua meta-package and unify telemetry opt-out (#1225)
* feat: add cua meta-package and unify telemetry opt-out

Meta-package (pip install cua):
- New libs/python/cua package exposing unified API:
  from cua import Sandbox, Image, ComputerAgent
- Depends on cua-sandbox, cua-agent[cloud], cua-cli
- cua-agent surface uses lazy __getattr__ imports to avoid
  import-time side effects when only sandbox symbols are needed
- .bumpversion.cfg, cd-py-cua.yml publish workflow, and
  pypi/cua entry in release-bump-version.yml

Telemetry:
- Unify opt-out: CUA_TELEMETRY_ENABLED=false is now canonical
  for both PostHog and OTEL; CUA_TELEMETRY_DISABLED emits a
  DeprecationWarning and is honoured for backwards compatibility
- Move installation ID from site-packages to ~/.config/cua/
  so it survives upgrades and is shared across venvs
- Add cua-core dep to cua-sandbox; instrument sandbox lifecycle
  with sandbox_create and sandbox_destroy PostHog events;
  add telemetry_enabled param to create/connect/ephemeral
- Instrument cua-cli: cli_command event on every invocation
  via try/finally (command, subcommand, status, duration_seconds)
- Fix TESTING.md to use CUA_TELEMETRY_ENABLED=false

* fix: correct docstring/README sandbox scope and Windows telemetry env var

* fix(core): fix telemetry tests failing when CUA_TELEMETRY_DISABLED is set in CI

- Clear CUA_TELEMETRY_DISABLED env var in tests that assert telemetry is enabled
- Fix Path.home() mock chain to match actual usage pattern
- Fix read_text().strip() mock to return string instead of MagicMock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: replace deprecated CUA_TELEMETRY_DISABLED with CUA_TELEMETRY_ENABLED=false

Update CI workflows, all test conftest.py fixtures, and comments to use
the current CUA_TELEMETRY_ENABLED=false env var instead of the deprecated
CUA_TELEMETRY_DISABLED=1, eliminating DeprecationWarnings that were
causing test failures.

Also fix isort import ordering in cua-sandbox and computer-server files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(lint): apply black formatting to 14 files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(lint): fix 4 ruff errors (unused vars, ambiguous name)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(lint): fix remaining isort and black issues

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add SandboxComputerHandler and linux agent example

- Add SandboxComputerHandler in agent/computers/sandbox.py that adapts
  cua_sandbox.Sandbox to the AsyncComputerHandler protocol
- Wire Sandbox recognition into is_agent_computer() and make_computer_handler()
  so tools=[sb] works the same as the old Computer wrapper
- Normalize Anthropic/X11 key names (e.g. Return → enter) to pynput names
  used by computer-server's linux handler
- Add examples/agents/test_linux_agent.py demonstrating Sandbox.ephemeral
  with ComputerAgent using an Anthropic model
- Lower cua-agent requires-python to >=3.11 for broader compatibility
- Add cua-agent as editable dev dep in cua-sandbox for testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: support Python 3.11 in cua-agent and cua-core

- Drop cua-computer from cua-agent required deps (move to optional 'computer' extra)
- Make all 'from computer import' usages in agent optional (try/except)
- Fix typing.override import for Python <3.12 (use typing_extensions fallback)
- Lower requires-python to >=3.11 in cua-agent, cua-core, and cua-sandbox

Tested: 3.11 ✓  3.12 ✓  3.13 ✓

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(docs): update Sandbox API usage from deprecated os_type/provider_type to Image API

Replace all occurrences of the old cua-computer style parameters
(os_type=, provider_type=VMProviderType.*) with the correct cua-sandbox
Image API (Image.linux(), Image.macos(), Image.windows(), local=True).

Also remove VMProviderType from imports where no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: add Pillow to cua-agent core deps after dropping cua-computer

Pillow was previously a transitive dependency via cua-computer.
After making cua-computer optional, PIL imports fail. Add Pillow
directly to required dependencies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 15:32:13 -07:00

95 lines
2.5 KiB
YAML

name: "CI: Test Python"
on:
pull_request:
paths:
- "libs/python/**"
- ".github/workflows/ci-test-python.yml"
workflow_dispatch: # Allow manual trigger
jobs:
test:
name: Test ${{ matrix.package }}
runs-on: ubuntu-latest
strategy:
fail-fast: false # Test all packages even if one fails
matrix:
package:
- core
- agent
- computer
- computer-server
- mcp-server
- som
- cua-auto
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install uv
run: |
pip install uv
- name: Install package and dependencies
run: |
cd libs/python/${{ matrix.package }}
# Install the package in editable mode with dev dependencies
if [ -f pyproject.toml ]; then
uv pip install --system -e .
fi
shell: bash
- name: Install test dependencies
run: |
# Install test dependencies from root pyproject.toml if tests directory exists
# The root pyproject.toml has package=false, so we install just the dependency group
if [ -d "libs/python/${{ matrix.package }}/tests" ]; then
uv pip install --system --group test
fi
shell: bash
- name: Run tests
run: |
cd libs/python/${{ matrix.package }}
if [ -d tests ]; then
python -m pytest tests/ -v --tb=short --cov --cov-report=term --cov-report=xml
else
echo "No tests directory found, skipping tests"
fi
shell: bash
env:
CUA_TELEMETRY_ENABLED: "false" # Disable telemetry during tests
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
if: always()
with:
file: ./libs/python/${{ matrix.package }}/coverage.xml
flags: ${{ matrix.package }}
name: codecov-${{ matrix.package }}
fail_ci_if_error: false
continue-on-error: true
summary:
name: Test Summary
runs-on: ubuntu-latest
needs: test
if: always()
steps:
- name: Check test results
run: |
if [ "${{ needs.test.result }}" == "failure" ]; then
echo "❌ Some tests failed. Please check the logs above."
exit 1
else
echo "✅ All tests passed!"
fi