Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/cd-py-cua.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: "CD: cua (PyPI)"

on:
push:
tags:
- "cua-v*"
workflow_dispatch:
inputs:
version:
description: "Version to publish (without v prefix)"
required: true
default: "0.1.0"
workflow_call:
inputs:
version:
description: "Version to publish"
required: true
type: string

permissions:
contents: write

jobs:
prepare:
runs-on: macos-latest
outputs:
version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@v4

- name: Determine version
id: get-version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION=${{ inputs.version }}
elif [ "${{ github.event_name }}" == "push" ]; then
if [[ "${{ github.ref }}" =~ ^refs/tags/cua-v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
VERSION=${BASH_REMATCH[1]}
else
echo "Invalid tag format for cua"
exit 1
fi
elif [ -n "${{ github.event.inputs.version }}" ]; then
VERSION=${{ github.event.inputs.version }}
else
echo "ERROR: No version found!"
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT

publish:
needs: prepare
uses: ./.github/workflows/py-reusable-publish.yml
with:
package_name: "cua"
package_dir: "libs/python/cua"
version: ${{ needs.prepare.outputs.version }}
base_package_name: "cua"
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}

create-release:
needs: [prepare, publish]
uses: ./.github/workflows/release-github-reusable.yml
with:
tag_name: "cua-v${{ needs.prepare.outputs.version }}"
release_name: "cua v${{ needs.prepare.outputs.version }}"
module_path: "libs/python/cua"
body: ""
2 changes: 1 addition & 1 deletion .github/workflows/ci-test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
fi
shell: bash
env:
CUA_TELEMETRY_DISABLED: "1" # Disable telemetry during tests
CUA_TELEMETRY_ENABLED: "false" # Disable telemetry during tests

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/claude-auto-fix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ jobs:
FIXING TEST FAILURES:
For Python test failures:
- Run the specific failing test: uv run python -m pytest libs/python/<package>/tests/ -v --tb=long
- The test environment uses CUA_TELEMETRY_DISABLED=1
- The test environment uses CUA_TELEMETRY_ENABLED=false
- Tests use pytest-asyncio with asyncio_mode=auto
For TypeScript build/type failures:
- Check types: node ./scripts/typescript-typecheck.js
Expand Down Expand Up @@ -311,7 +311,7 @@ jobs:
ANTHROPIC_BEDROCK_BASE_URL: "https://bedrock-runtime.us-west-2.amazonaws.com"
AWS_REGION: us-west-2
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CUA_TELEMETRY_DISABLED: "1"
CUA_TELEMETRY_ENABLED: "false"
CLAUDE_CODE_ENABLE_TELEMETRY: "1"
OTEL_METRICS_EXPORTER: otlp
OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/release-bump-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
required: true
type: choice
options:
- pypi/cua
- pypi/agent
- pypi/auto
- pypi/bench
Expand Down Expand Up @@ -52,6 +53,10 @@ jobs:
id: package
run: |
case "${{ inputs.service }}" in
"pypi/cua")
echo "directory=libs/python/cua" >> $GITHUB_OUTPUT
echo "type=python" >> $GITHUB_OUTPUT
;;
"pypi/agent")
echo "directory=libs/python/agent" >> $GITHUB_OUTPUT
echo "type=python" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -213,6 +218,15 @@ jobs:
echo "Tags to push: $ALL_TAGS"
echo "tags=$ALL_TAGS" >> $GITHUB_OUTPUT

- name: Capture bumped cua version
if: ${{ inputs.service == 'pypi/cua' }}
id: cua_version
run: |
cd libs/python/cua
VERSION=$(python -c "import tomllib; from pathlib import Path; data = tomllib.loads(Path('pyproject.toml').read_text()); print(data['project']['version'])")
echo "cua version: $VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Capture bumped agent version
if: ${{ inputs.service == 'pypi/agent' }}
id: agent_version
Expand Down
4 changes: 2 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cd libs/python/core
pip install -e .

# Run tests
export CUA_TELEMETRY_DISABLED=1 # or $env:CUA_TELEMETRY_DISABLED="1" on Windows
export CUA_TELEMETRY_ENABLED=false # or $env:CUA_TELEMETRY_ENABLED="false" on Windows
pytest tests/ -v
```

Expand Down Expand Up @@ -87,7 +87,7 @@ Tests run automatically on every PR via GitHub Actions (`.github/workflows/ci-py

**ModuleNotFoundError**: Run `pip install -e .` in package directory

**Tests fail in CI but pass locally**: Set `CUA_TELEMETRY_DISABLED=1`
**Tests fail in CI but pass locally**: Set `CUA_TELEMETRY_ENABLED=false`

**Async tests error**: Install `pytest-asyncio` and use `@pytest.mark.asyncio`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -170,8 +170,7 @@ async def complex_ui_navigation():
"""
try:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.CLOUD,
Image.linux(),
name=os.environ["CUA_SANDBOX_NAME"],
api_key=os.environ["CUA_API_KEY"],
verbosity=logging.INFO,
Expand Down Expand Up @@ -300,7 +299,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -316,10 +315,9 @@ async def complex_ui_navigation():
with complex, multi-step navigation tasks.
"""
try:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.DOCKER,
image="trycua/cua-xfce:latest",
async with Sandbox.ephemeral(
Image.linux(),
local=True,
verbosity=logging.INFO,
) as computer:

Expand Down Expand Up @@ -424,7 +422,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -441,8 +439,8 @@ async def complex_ui_navigation():
"""
try:
async with Sandbox.create(
os_type="macos",
provider_type=VMProviderType.LUME,
Image.macos(),
local=True,
name="macos-sequoia-cua:latest",
verbosity=logging.INFO,
) as computer:
Expand Down
26 changes: 12 additions & 14 deletions docs/content/docs/cua/examples/automation/form-filling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -81,8 +81,7 @@ def handle_sigint(sig, frame):
async def fill_application():
try:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.CLOUD,
Image.linux(),
name="your-sandbox-name", # Replace with your sandbox name
api_key=os.environ["CUA_API_KEY"],
verbosity=logging.INFO,
Expand Down Expand Up @@ -175,7 +174,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -187,10 +186,9 @@ def handle_sigint(sig, frame):

async def fill_application():
try:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.DOCKER,
image="trycua/cua-xfce:latest", # or "trycua/cua-ubuntu:latest"
async with Sandbox.ephemeral(
Image.linux(),
local=True,
verbosity=logging.INFO,
) as computer:

Expand Down Expand Up @@ -275,7 +273,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -288,8 +286,8 @@ def handle_sigint(sig, frame):
async def fill_application():
try:
async with Sandbox.create(
os_type="macos",
provider_type=VMProviderType.LUME,
Image.macos(),
local=True,
name="macos-sequoia-cua:latest",
verbosity=logging.INFO,
) as computer:
Expand Down Expand Up @@ -375,7 +373,7 @@ import signal
import traceback

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -388,8 +386,8 @@ def handle_sigint(sig, frame):
async def fill_application():
try:
async with Sandbox.create(
os_type="windows",
provider_type=VMProviderType.WINDOWS_SANDBOX,
Image.windows(),
local=True,
verbosity=logging.INFO,
) as computer:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ import traceback
from datetime import datetime

from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -232,8 +232,7 @@ async def scrape_linkedin_connections():

try:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.CLOUD,
Image.linux(),
name=os.environ["CUA_CONTAINER_NAME"], # Your sandbox name
api_key=os.environ["CUA_API_KEY"],
verbosity=logging.INFO,
Expand Down Expand Up @@ -394,10 +393,9 @@ if __name__ == "__main__":

```python
# Same code as Cloud Sandbox, but change Sandbox initialization to:
async with Sandbox.create(
os_type="linux",
provider_type=VMProviderType.DOCKER,
image="trycua/cua-xfce:latest",
async with Sandbox.ephemeral(
Image.linux(),
local=True,
verbosity=logging.INFO,
) as computer:
```
Expand All @@ -410,8 +408,8 @@ And remove the `CUA_API_KEY` and `CUA_CONTAINER_NAME` requirements from `.env` a
```python
# Same code as Cloud Sandbox, but change Sandbox initialization to:
async with Sandbox.create(
os_type="macos",
provider_type=VMProviderType.LUME,
Image.macos(),
local=True,
name="macos-sequoia-cua:latest",
verbosity=logging.INFO,
) as computer:
Expand All @@ -425,8 +423,8 @@ And remove the `CUA_API_KEY` and `CUA_CONTAINER_NAME` requirements from `.env` a
```python
# Same code as Cloud Sandbox, but change Sandbox initialization to:
async with Sandbox.create(
os_type="windows",
provider_type=VMProviderType.WINDOWS_SANDBOX,
Image.windows(),
local=True,
verbosity=logging.INFO,
) as computer:
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ import asyncio
import logging
import os
from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -173,8 +173,7 @@ async def automate_hr_workflow():
try:
# Connect to Windows Cloud Sandbox with VPN
async with Sandbox.create(
os_type="windows",
provider_type=VMProviderType.CLOUD,
Image.windows(),
name=os.environ["CUA_SANDBOX_NAME"],
api_key=os.environ["CUA_API_KEY"],
verbosity=logging.INFO,
Expand Down Expand Up @@ -265,7 +264,7 @@ import asyncio
import logging
import os
from agent import ComputerAgent
from cua_sandbox import Sandbox, Image, VMProviderType
from cua_sandbox import Sandbox, Image
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
Expand All @@ -277,8 +276,8 @@ async def automate_hr_workflow():
try:
# Connect to Windows Sandbox
async with Sandbox.create(
os_type="windows",
provider_type=VMProviderType.WINDOWS_SANDBOX,
Image.windows(),
local=True,
verbosity=logging.INFO,
) as computer:

Expand Down
3 changes: 1 addition & 2 deletions docs/content/docs/cua/guide/fundamentals/agent-loops.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ from cua_sandbox import Sandbox, Image

async def take_screenshot():
async with Sandbox.create(
os_type="linux",
provider_type="cloud",
Image.linux(),
name="your-sandbox-name",
api_key="your-api-key"
) as computer:
Expand Down
Loading
Loading