Skip to content

Rename agent/core packages to cua_agent/cua_core to avoid namespace collisions - #1319

Merged
ddupont808 merged 3 commits into
mainfrom
claude/slack-session-EBTpH
Apr 15, 2026
Merged

Rename agent/core packages to cua_agent/cua_core to avoid namespace collisions#1319
ddupont808 merged 3 commits into
mainfrom
claude/slack-session-EBTpH

Conversation

@ddupont808

@ddupont808 ddupont808 commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator
  • Rename libs/python/agent/agent/ to libs/python/agent/cua_agent/
  • Rename libs/python/core/core/ to libs/python/core/cua_core/
  • Update all imports from 'agent' to 'cua_agent'
  • Update all imports from 'core' to 'cua_core'
  • Pin cua-core dependency to >=0.3.0,<0.4.0 across all packages
  • Pin cua-agent dependency to >=0.8.0 across all packages
  • Update documentation and blog posts with new import paths

Fixes CUA-445

https://claude.ai/code/session_013snU7pHE5ZNs6nEzjHmLXR

Summary by CodeRabbit

  • Documentation

    • Updated code examples and import statements across guides and blog posts to reflect package namespace organization.
  • Chores

    • Updated internal dependencies and package build configurations.
    • Bumped minimum required versions for core and agent packages.

…ollisions

- Rename libs/python/agent/agent/ to libs/python/agent/cua_agent/
- Rename libs/python/core/core/ to libs/python/core/cua_core/
- Update all imports from 'agent' to 'cua_agent'
- Update all imports from 'core' to 'cua_core'
- Pin cua-core dependency to >=0.3.0,<0.4.0 across all packages
- Pin cua-agent dependency to >=0.8.0 across all packages
- Update documentation and blog posts with new import paths

Fixes CUA-445

https://claude.ai/code/session_013snU7pHE5ZNs6nEzjHmLXR
@vercel

vercel Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Apr 15, 2026 8:21pm

Request Review

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5e9a8f7f-6578-4e07-88d4-afdcc1077369

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR performs a comprehensive namespace refactoring across the codebase, updating import paths from agent and core package prefixes to cua_agent and cua_core respectively. Dependency version constraints are updated in multiple pyproject.toml files (minimum cua-core to 0.3.0+ and cua-agent to 0.8.0+), and build configurations are modified to include cua_agent/ and cua_core/ directories instead of agent/ and core/.

Changes

Cohort / File(s) Summary
Documentation blog posts
blog/build-your-own-operator-on-macos-2.md, blog/hud-agent-evals.md, blog/human-in-the-loop.md
Updated example code imports from agent.* and cua_agent.* namespace packages in Gradio UI, HUD integration, and ComputerAgent usage snippets.
Documentation guides
docs/content/docs/cua/guide/advanced/custom-tools.mdx, docs/content/docs/cua/guide/fundamentals/agent-loops.mdx, docs/content/docs/cua/guide/fundamentals/callbacks.mdx, docs/content/docs/cua/guide/integrations/hud.mdx
Updated import paths in code examples from agent.* to cua_agent.* and core.* to cua_core.* for BrowserTool, BudgetExceededException, AsyncCallbackHandler, and HUD functions.
Agent core modules
libs/python/agent/cua_agent/agent.py, libs/python/agent/cua_agent/adapters/cua_adapter.py, libs/python/agent/cua_agent/callbacks/telemetry.py, libs/python/agent/cua_agent/ui/gradio/app.py
Updated imports for telemetry functions, version headers, and Gradio UI components from core.telemetry/core.http to cua_core.telemetry/cua_core.http, and internal imports from agent.* to cua_agent.*.
Agent HUD integration
libs/python/agent/cua_agent/integrations/hud/__init__.py, libs/python/agent/cua_agent/integrations/hud/agent.py, libs/python/agent/cua_agent/integrations/hud/proxy.py
Updated imports for ComputerAgent, callback handlers, and utility functions from agent.* to cua_agent.* package namespace.
Agent loops and export configs
libs/python/agent/cua_agent/loops/__init__.py, libs/python/agent/cua_agent/loops/gelato.py, libs/python/agent/cua_agent/loops/uiins.py
Whitespace and formatting normalization; no functional code changes to SYSTEM_PROMPT, coordinate extraction, or agent prediction logic.
Agent package dependencies & build
libs/python/agent/pyproject.toml, libs/python/agent/benchmarks/utils.py, libs/python/agent/tests/test_tool_resolution.py
Updated cua-core from ≥0.1.18,<0.2.0 to ≥0.3.0,<0.4.0, build includes from agent/ to cua_agent/, and imports in benchmarks and tests from agent.* to cua_agent.*.
Core package exports & build
libs/python/core/cua_core/__init__.py, libs/python/core/cua_core/telemetry/__init__.py, libs/python/core/pyproject.toml
Updated re-exported imports from core.http/core.telemetry.* to cua_core.http/cua_core.telemetry.*, and build includes from core/ to cua_core/.
Computer package
libs/python/computer/computer/computer.py, libs/python/computer/computer/interface/generic.py, libs/python/computer/computer/providers/cloud/provider.py, libs/python/computer/computer/providers/cloud/providerv2.py, libs/python/computer/pyproject.toml
Updated telemetry and version header imports from core.telemetry/core.http to cua_core.telemetry/cua_core.http; updated cua-core dependency from ≥0.1.18,<0.2.0 to ≥0.3.0,<0.4.0.
Computer server
libs/python/computer-server/computer_server/main.py, libs/python/computer-server/pyproject.toml
Updated telemetry module import from core.telemetry to cua_core.telemetry and conditional agent import from agent to cua_agent; updated cua-core dependency constraint.
CLI package
libs/python/cua-cli/cua_cli/api/client.py, libs/python/cua-cli/cua_cli/commands/auth.py, libs/python/cua-cli/cua_cli/commands/workspace.py, libs/python/cua-cli/pyproject.toml
Updated version header imports from core.http to cua_core.http across CLI commands; updated cua-core dependency to ≥0.3.0,<0.4.0.
Metapackage and aggregators
libs/python/cua/cua/callbacks.py, libs/python/cua/cua/tools.py, libs/python/cua/pyproject.toml
Updated re-exports of callback and tool classes from agent.callbacks/agent.tools to cua_agent.callbacks/cua_agent.tools; updated cua-agent[cloud] dependency to ≥0.8.0.
Sandbox and supplementary packages
libs/python/cua-bench/cua_bench/telemetry/events.py, libs/python/cua-bench/pyproject.toml, libs/python/cua-sandbox/pyproject.toml, libs/python/mcp-server/pyproject.toml
Updated telemetry imports from core.telemetry to cua_core.telemetry; updated dependency constraints for cua-core (≥0.3.0,<0.4.0) and cua-agent (≥0.8.0).
Tests and scripts
tests/test_telemetry.py, scripts/playground.sh
Updated telemetry module import to cua_core.telemetry; updated generated playground script imports from agent.* to cua_agent.* for ComputerAgent, LLM, AgentLoop, and Gradio UI components.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

release:pypi/agent, release:pypi/core, release:pypi/computer, release:pypi/computer-server, release:pypi/cli

Suggested reviewers

  • r33drichards

Poem

🐰 Hopping through files with careful paws,
We've renamed the paths without a flaw,
From agent to cua_agent so bright,
And core to cua_core—feels just right!
Version bumps dance as dependencies align,
A refactored codebase? Now that's divine! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: renaming packages from agent/core to cua_agent/cua_core for namespace collision avoidance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/slack-session-EBTpH

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

📦 Publishable packages changed

  • pypi/agent
  • pypi/bench
  • pypi/cli
  • pypi/computer
  • pypi/computer-server
  • pypi/core
  • pypi/mcp-server

Add release:<service> labels to auto-release on merge (+ optional bump:minor or bump:major, default is patch).
Or add no-release to skip.

@sentry

sentry Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.63636% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ibs/python/computer-server/computer_server/main.py 25.00% 3 Missing ⚠️
libs/python/agent/cua_agent/loops/__init__.py 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (1)
libs/python/agent/cua_agent/loops/__init__.py (1)

1-3: Consider updating the docstring for consistency with the new namespace.

The docstring still references "agent loops for agent" which could be updated to "Agent loops for cua_agent" or simplified to just "Agent loops" for better clarity after the namespace refactoring.

📝 Suggested docstring update
-"""
-Agent loops for agent
-"""
+"""
+Agent loops for cua_agent
+"""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/__init__.py` around lines 1 - 3, Update the
module docstring in __init__.py to reflect the new namespace by replacing the
current text "Agent loops for agent" with a clearer description such as "Agent
loops for cua_agent" or simply "Agent loops"; edit the top-of-file module
docstring in the cua_agent.loops package to use the chosen wording so the
docstring matches the refactored namespace.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@blog/build-your-own-operator-on-macos-2.md`:
- Line 484: Search the article for any occurrences of the stale import "from
agent import ComputerAgent" (e.g., in the snippets around the earlier blocks
that also import create_gradio_ui) and update each to import the renamed
package, replacing it with "from cua_agent.agent import ComputerAgent" so the
examples match the current layout and won't fail at runtime.

In `@libs/python/agent/cua_agent/loops/gelato.py`:
- Around line 122-124: Wrap the base64 decode and PIL image open steps (lines
handling image_b64, image_data, and image) in a try/except that catches (at
minimum) binascii.Error/ValueError for invalid base64 and
PIL.UnidentifiedImageError/OSError for invalid/corrupt image data; on exception,
log a clear error including the offending image identifier/context and return or
raise a controlled exception so callers can handle it (update the block that
assigns image_data = base64.b64decode(image_b64) and image =
Image.open(BytesIO(image_data)) to use this error handling).
- Around line 28-41: The extract_coordinates function currently uses a bare
except and returns (0, 0) on failure; change it to use specific exception logic:
use re.findall as before, convert matches to floats (tuple(map(float, match)))
and if no matches are found raise a ValueError with a clear message (do not
return (0, 0)), and only catch the narrow exceptions you expect
(TypeError/IndexError) if needed and re-raise them as ValueError with context;
reference extract_coordinates, re.findall, matches, and the tuple(map(...))
conversion when making the change.
- Around line 169-172: Wrap the await litellm.acompletion(**api_kwargs) call in
a try/except to catch network/API errors and log or re-raise a descriptive
error, then validate the response structure before accessing it: check that
response is not None, response.choices exists and is a non-empty list, and that
response.choices[0].message and response.choices[0].message.content are present;
if validation fails, handle gracefully (return an error value or raise a clear
exception). Update the code around litellm.acompletion and the output_text
extraction to use these checks and ensure any exceptions include context (e.g.,
API name and api_kwargs summary) so failures are informative.

In `@libs/python/agent/cua_agent/loops/uiins.py`:
- Around line 167-171: The function currently multiplies pred_x/pred_y from
parse_coordinates and always returns floored coordinates even when parse failed
(parse_coordinates returned an invalid sentinel like (-1, -1)); update the logic
in the function containing the parse_coordinates call to detect an invalid parse
result (e.g., check for None or the sentinel values returned by
parse_coordinates) before scaling, and return None immediately if parsing failed
so the method honors its "return None on prediction failure" contract; reference
the parse_coordinates call and the pred_x/pred_y handling (and scale_x/scale_y
usage) when applying this guard.
- Around line 42-56: The smart_resize logic can divide by zero when total_pixels
== 0; update the smart_resize function to guard against zero-sized inputs by
checking if height <= 0 or width <= 0 or total_pixels == 0 before the scaling
logic (where total_pixels = height * width is computed) and handle it by
returning a sensible default (e.g., nearest positive multiple of factor or
raising a clear ValueError) or clamping to min_pixels behavior; ensure
references to total_pixels, height, width, factor, min_pixels, max_pixels are
updated so the early-return or error prevents any subsequent division by
total_pixels.
- Around line 110-165: predict_click currently assumes successful base64 decode,
image processing, model call and response shape; wrap the whole
decoding/resizing/acompletion/response-extraction flow in a try/except to return
None on any failure and log the exception. Specifically, guard the
base64.b64decode/Image.open/BytesIO steps that use image_b64, the
smart_resize+resize logic (resized_image_b64), the litellm.acompletion call, and
the response parsing that reads response.choices[0].message.content; on
exception catch and log the exception (or use an existing logger) and return
None so the documented fallback is honored. Ensure you validate the response
structure (presence of choices, index 0, message, and content) before accessing
and return None if shape is unexpected.

In `@libs/python/agent/pyproject.toml`:
- Line 22: The package manifest currently pins the package version at version =
"0.7.39" which conflicts with downstream requirements; update the package
version string for cua-agent to at least "0.8.0" (e.g., change version =
"0.7.39" to version = "0.8.0") in pyproject.toml and ensure any related metadata
(package __version__ if present) is kept in sync so consumers requiring
cua-agent>=0.8.0 will resolve correctly.

In `@libs/python/computer-server/computer_server/main.py`:
- Line 44: This module still imports the old namespaces (core.http and
agent.computers) which breaks auth and the /responses routes; update the import
lines so they reference the migrated package paths used elsewhere (e.g., import
the HTTP utilities and types from the new cua_agent namespace and import
ComputerAgent from the new agent package) and adjust any local references if the
module path or symbol names changed; specifically replace usages/imports of
core.http and agent.computers with their new equivalents used by ComputerAgent
(ensure auth handlers and the /responses route reference the updated modules),
and run a quick grep for core.http and agent.computers to confirm all
imports/usages are migrated.

In `@libs/python/mcp-server/pyproject.toml`:
- Line 16: Import resolution breaks because code still uses the legacy module
export "from agent import ComputerAgent" while the package now exposes the class
as cua_agent.agent.ComputerAgent; update the import in mcp-server server module
to "from cua_agent.agent import ComputerAgent" (and similarly migrate any other
"from agent ..." imports) or else revert the pyproject bump (keep
"cua-agent[all]<0.8.0") until the migration is complete so the existing imports
remain valid.

In `@scripts/playground.sh`:
- Around line 259-260: The import line in the generated run_demo.py templates
incorrectly includes non-existent and unused symbols LLM, AgentLoop, and
LLMProvider from cua_agent; remove those three names so the import reads only
import ComputerAgent (leave the separate from cua_agent.ui.gradio.ui_components
import create_gradio_ui as-is), and apply this same change to both generated
run_demo.py templates (cloud and local branches) to prevent startup import
failures.

---

Nitpick comments:
In `@libs/python/agent/cua_agent/loops/__init__.py`:
- Around line 1-3: Update the module docstring in __init__.py to reflect the new
namespace by replacing the current text "Agent loops for agent" with a clearer
description such as "Agent loops for cua_agent" or simply "Agent loops"; edit
the top-of-file module docstring in the cua_agent.loops package to use the
chosen wording so the docstring matches the refactored namespace.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b0f7d60a-470b-4264-ae2e-9d988814bbb9

📥 Commits

Reviewing files that changed from the base of the PR and between 30410b9 and b60455d.

⛔ Files ignored due to path filters (1)
  • libs/python/agent/cua_agent/loops/model_types.csv is excluded by !**/*.csv
📒 Files selected for processing (115)
  • blog/build-your-own-operator-on-macos-2.md
  • blog/hud-agent-evals.md
  • blog/human-in-the-loop.md
  • docs/content/docs/cua/guide/advanced/custom-tools.mdx
  • docs/content/docs/cua/guide/fundamentals/agent-loops.mdx
  • docs/content/docs/cua/guide/fundamentals/callbacks.mdx
  • docs/content/docs/cua/guide/integrations/hud.mdx
  • libs/cua-bench/cua_bench/telemetry/events.py
  • libs/cua-bench/pyproject.toml
  • libs/python/agent/benchmarks/utils.py
  • libs/python/agent/cua_agent/__init__.py
  • libs/python/agent/cua_agent/__main__.py
  • libs/python/agent/cua_agent/adapters/__init__.py
  • libs/python/agent/cua_agent/adapters/azure_ml_adapter.py
  • libs/python/agent/cua_agent/adapters/cua_adapter.py
  • libs/python/agent/cua_agent/adapters/huggingfacelocal_adapter.py
  • libs/python/agent/cua_agent/adapters/human_adapter.py
  • libs/python/agent/cua_agent/adapters/mlxvlm_adapter.py
  • libs/python/agent/cua_agent/adapters/models/__init__.py
  • libs/python/agent/cua_agent/adapters/models/generic.py
  • libs/python/agent/cua_agent/adapters/models/internvl.py
  • libs/python/agent/cua_agent/adapters/models/opencua.py
  • libs/python/agent/cua_agent/adapters/models/qwen2_5_vl.py
  • libs/python/agent/cua_agent/adapters/yutori_adapter.py
  • libs/python/agent/cua_agent/agent.py
  • libs/python/agent/cua_agent/callbacks/__init__.py
  • libs/python/agent/cua_agent/callbacks/base.py
  • libs/python/agent/cua_agent/callbacks/budget_manager.py
  • libs/python/agent/cua_agent/callbacks/image_retention.py
  • libs/python/agent/cua_agent/callbacks/logging.py
  • libs/python/agent/cua_agent/callbacks/operator_validator.py
  • libs/python/agent/cua_agent/callbacks/otel.py
  • libs/python/agent/cua_agent/callbacks/pii_anonymization.py
  • libs/python/agent/cua_agent/callbacks/prompt_instructions.py
  • libs/python/agent/cua_agent/callbacks/telemetry.py
  • libs/python/agent/cua_agent/callbacks/trajectory_saver.py
  • libs/python/agent/cua_agent/cli.py
  • libs/python/agent/cua_agent/computers/__init__.py
  • libs/python/agent/cua_agent/computers/base.py
  • libs/python/agent/cua_agent/computers/cua.py
  • libs/python/agent/cua_agent/computers/custom.py
  • libs/python/agent/cua_agent/computers/sandbox.py
  • libs/python/agent/cua_agent/decorators.py
  • libs/python/agent/cua_agent/human_tool/__init__.py
  • libs/python/agent/cua_agent/human_tool/__main__.py
  • libs/python/agent/cua_agent/human_tool/server.py
  • libs/python/agent/cua_agent/human_tool/ui.py
  • libs/python/agent/cua_agent/integrations/hud/__init__.py
  • libs/python/agent/cua_agent/integrations/hud/agent.py
  • libs/python/agent/cua_agent/integrations/hud/proxy.py
  • libs/python/agent/cua_agent/loops/__init__.py
  • libs/python/agent/cua_agent/loops/anthropic.py
  • libs/python/agent/cua_agent/loops/base.py
  • libs/python/agent/cua_agent/loops/composed_grounded.py
  • libs/python/agent/cua_agent/loops/fara/__init__.py
  • libs/python/agent/cua_agent/loops/fara/config.py
  • libs/python/agent/cua_agent/loops/fara/helpers.py
  • libs/python/agent/cua_agent/loops/fara/schema.py
  • libs/python/agent/cua_agent/loops/gelato.py
  • libs/python/agent/cua_agent/loops/gemini.py
  • libs/python/agent/cua_agent/loops/generic_vlm.py
  • libs/python/agent/cua_agent/loops/glm45v.py
  • libs/python/agent/cua_agent/loops/gta1.py
  • libs/python/agent/cua_agent/loops/holo.py
  • libs/python/agent/cua_agent/loops/internvl.py
  • libs/python/agent/cua_agent/loops/moondream3.py
  • libs/python/agent/cua_agent/loops/omniparser.py
  • libs/python/agent/cua_agent/loops/openai.py
  • libs/python/agent/cua_agent/loops/opencua.py
  • libs/python/agent/cua_agent/loops/qwen35.py
  • libs/python/agent/cua_agent/loops/qwen3vl.py
  • libs/python/agent/cua_agent/loops/uiins.py
  • libs/python/agent/cua_agent/loops/uitars.py
  • libs/python/agent/cua_agent/loops/uitars2.py
  • libs/python/agent/cua_agent/loops/yutori.py
  • libs/python/agent/cua_agent/playground/__init__.py
  • libs/python/agent/cua_agent/playground/server.py
  • libs/python/agent/cua_agent/proxy/examples.py
  • libs/python/agent/cua_agent/proxy/handlers.py
  • libs/python/agent/cua_agent/responses.py
  • libs/python/agent/cua_agent/tools/__init__.py
  • libs/python/agent/cua_agent/tools/base.py
  • libs/python/agent/cua_agent/tools/browser_tool.py
  • libs/python/agent/cua_agent/types.py
  • libs/python/agent/cua_agent/ui/__init__.py
  • libs/python/agent/cua_agent/ui/__main__.py
  • libs/python/agent/cua_agent/ui/gradio/__init__.py
  • libs/python/agent/cua_agent/ui/gradio/app.py
  • libs/python/agent/cua_agent/ui/gradio/ui_components.py
  • libs/python/agent/pyproject.toml
  • libs/python/agent/tests/test_tool_resolution.py
  • libs/python/computer-server/computer_server/main.py
  • libs/python/computer-server/pyproject.toml
  • libs/python/computer/computer/computer.py
  • libs/python/computer/computer/interface/generic.py
  • libs/python/computer/computer/providers/cloud/provider.py
  • libs/python/computer/computer/providers/cloud/providerv2.py
  • libs/python/computer/pyproject.toml
  • libs/python/core/cua_core/__init__.py
  • libs/python/core/cua_core/http.py
  • libs/python/core/cua_core/telemetry/__init__.py
  • libs/python/core/cua_core/telemetry/otel.py
  • libs/python/core/cua_core/telemetry/posthog.py
  • libs/python/core/pyproject.toml
  • libs/python/cua-cli/cua_cli/api/client.py
  • libs/python/cua-cli/cua_cli/commands/auth.py
  • libs/python/cua-cli/cua_cli/commands/workspace.py
  • libs/python/cua-cli/pyproject.toml
  • libs/python/cua-sandbox/pyproject.toml
  • libs/python/cua/cua/callbacks.py
  • libs/python/cua/cua/tools.py
  • libs/python/cua/pyproject.toml
  • libs/python/mcp-server/pyproject.toml
  • scripts/playground.sh
  • tests/test_telemetry.py


```python
from agent.ui.gradio.app import create_gradio_ui
from cua_agent.ui.gradio.app import create_gradio_ui

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

This article still contains stale agent imports in earlier code blocks.

After this rename, examples at Line 214, Line 266, Line 358, and Line 578 still use from agent import ComputerAgent, which will mislead users and fail with the new package layout.

📝 Suggested updates
- from agent import ComputerAgent
+ from cua_agent import ComputerAgent

Apply this replacement to each outdated snippet in the post.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blog/build-your-own-operator-on-macos-2.md` at line 484, Search the article
for any occurrences of the stale import "from agent import ComputerAgent" (e.g.,
in the snippets around the earlier blocks that also import create_gradio_ui) and
update each to import the renamed package, replacing it with "from
cua_agent.agent import ComputerAgent" so the examples match the current layout
and won't fail at runtime.

Comment on lines +28 to +41
def extract_coordinates(raw_string):
"""
Extract the coordinates from the raw string.
Args:
raw_string: str (e.g. "(100, 200)")
Returns:
x: float (e.g. 100.0)
y: float (e.g. 200.0)
"""
try:
matches = re.findall(r"\((-?\d*\.?\d+),\s*(-?\d*\.?\d+)\)", raw_string)
return [tuple(map(int, match)) for match in matches][0]
except:
return 0, 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Replace bare except: with specific exception handling and improve error signaling.

The bare except: clause catches all exceptions including system-level ones (KeyboardInterrupt, SystemExit). Additionally, returning (0, 0) on parsing failure is misleading since (0, 0) is a valid coordinate—this could cause silent failures where clicks are incorrectly placed at the top-left corner instead of failing explicitly.

🛡️ Proposed fix
 def extract_coordinates(raw_string):
     """
     Extract the coordinates from the raw string.
     Args:
         raw_string: str (e.g. "(100, 200)")
     Returns:
         x: float (e.g. 100.0)
         y: float (e.g. 200.0)
     """
     try:
         matches = re.findall(r"\((-?\d*\.?\d+),\s*(-?\d*\.?\d+)\)", raw_string)
+        if not matches:
+            raise ValueError(f"No coordinate pattern found in: {raw_string}")
         return [tuple(map(int, match)) for match in matches][0]
-    except:
-        return 0, 0
+    except (ValueError, IndexError) as e:
+        raise ValueError(f"Failed to extract coordinates from '{raw_string}': {e}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/gelato.py` around lines 28 - 41, The
extract_coordinates function currently uses a bare except and returns (0, 0) on
failure; change it to use specific exception logic: use re.findall as before,
convert matches to floats (tuple(map(float, match))) and if no matches are found
raise a ValueError with a clear message (do not return (0, 0)), and only catch
the narrow exceptions you expect (TypeError/IndexError) if needed and re-raise
them as ValueError with context; reference extract_coordinates, re.findall,
matches, and the tuple(map(...)) conversion when making the change.

Comment on lines +122 to +124
image_data = base64.b64decode(image_b64)
image = Image.open(BytesIO(image_data))
width, height = image.width, image.height

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for image decoding operations.

The base64 decoding and image opening operations can fail (invalid base64, corrupted image data) but lack error handling. This could cause the method to raise unexpected exceptions.

🛡️ Proposed fix
+        try:
-        # Decode base64 image
-        image_data = base64.b64decode(image_b64)
-        image = Image.open(BytesIO(image_data))
+            # Decode base64 image
+            image_data = base64.b64decode(image_b64)
+            image = Image.open(BytesIO(image_data))
+        except (base64.binascii.Error, Exception) as e:
+            raise ValueError(f"Failed to decode or open image: {e}")
         width, height = image.width, image.height
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
image_data = base64.b64decode(image_b64)
image = Image.open(BytesIO(image_data))
width, height = image.width, image.height
try:
# Decode base64 image
image_data = base64.b64decode(image_b64)
image = Image.open(BytesIO(image_data))
except (base64.binascii.Error, Exception) as e:
raise ValueError(f"Failed to decode or open image: {e}")
width, height = image.width, image.height
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/gelato.py` around lines 122 - 124, Wrap the
base64 decode and PIL image open steps (lines handling image_b64, image_data,
and image) in a try/except that catches (at minimum) binascii.Error/ValueError
for invalid base64 and PIL.UnidentifiedImageError/OSError for invalid/corrupt
image data; on exception, log a clear error including the offending image
identifier/context and return or raise a controlled exception so callers can
handle it (update the block that assigns image_data =
base64.b64decode(image_b64) and image = Image.open(BytesIO(image_data)) to use
this error handling).

Comment on lines +169 to +172
response = await litellm.acompletion(**api_kwargs)

# Extract response text
output_text = response.choices[0].message.content # type: ignore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for API call and response validation.

The liteLLM API call and response access lack error handling. Network failures, API errors, or unexpected response structures could cause uncaught exceptions.

🛡️ Proposed fix
-        # Use liteLLM acompletion
-        response = await litellm.acompletion(**api_kwargs)
-
-        # Extract response text
-        output_text = response.choices[0].message.content  # type: ignore
+        # Use liteLLM acompletion
+        try:
+            response = await litellm.acompletion(**api_kwargs)
+        except Exception as e:
+            raise RuntimeError(f"API call failed: {e}")
+
+        # Extract response text
+        if not response.choices or not response.choices[0].message.content:
+            raise ValueError("API response missing expected content")
+        output_text = response.choices[0].message.content
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/gelato.py` around lines 169 - 172, Wrap the
await litellm.acompletion(**api_kwargs) call in a try/except to catch
network/API errors and log or re-raise a descriptive error, then validate the
response structure before accessing it: check that response is not None,
response.choices exists and is a non-empty list, and that
response.choices[0].message and response.choices[0].message.content are present;
if validation fails, handle gracefully (return an error value or raise a clear
exception). Update the code around litellm.acompletion and the output_text
extraction to use these checks and ensure any exceptions include context (e.g.,
API name and api_kwargs summary) so failures are informative.

Comment on lines +42 to +56
total_pixels = height * width

# If already within bounds, return original dimensions
if min_pixels <= total_pixels <= max_pixels:
# Round to nearest factor
new_height = (height // factor) * factor
new_width = (width // factor) * factor
return new_height, new_width

# Calculate scaling factor
if total_pixels > max_pixels:
scale = (max_pixels / total_pixels) ** 0.5
else:
scale = (min_pixels / total_pixels) ** 0.5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against zero-sized inputs in smart_resize.

At Line 55, total_pixels can be zero for invalid/empty dimensions, causing a division-by-zero path.

Proposed fix
 def smart_resize(
@@
 ) -> Tuple[int, int]:
     """Smart resize function similar to qwen_vl_utils."""
     # Calculate the total pixels
     total_pixels = height * width
+    if height <= 0 or width <= 0:
+        return factor, factor
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/uiins.py` around lines 42 - 56, The
smart_resize logic can divide by zero when total_pixels == 0; update the
smart_resize function to guard against zero-sized inputs by checking if height
<= 0 or width <= 0 or total_pixels == 0 before the scaling logic (where
total_pixels = height * width is computed) and handle it by returning a sensible
default (e.g., nearest positive multiple of factor or raising a clear
ValueError) or clamping to min_pixels behavior; ensure references to
total_pixels, height, width, factor, min_pixels, max_pixels are updated so the
early-return or error prevents any subsequent division by total_pixels.

Comment on lines +167 to +171
pred_x, pred_y = parse_coordinates(output_text) # type: ignore
pred_x *= scale_x
pred_y *= scale_y

return (math.floor(pred_x), math.floor(pred_y))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Return None on invalid coordinate parse to match the method contract.

At Line 167, failed parsing yields (-1, -1), but the method still returns coordinates at Line 171. That violates the “None if prediction fails” contract and can propagate invalid clicks.

Proposed fix
-        pred_x, pred_y = parse_coordinates(output_text)  # type: ignore
-        pred_x *= scale_x
-        pred_y *= scale_y
-
-        return (math.floor(pred_x), math.floor(pred_y))
+        pred_x, pred_y = parse_coordinates(output_text)  # type: ignore
+        if pred_x < 0 or pred_y < 0:
+            return None
+
+        pred_x *= scale_x
+        pred_y *= scale_y
+        return (math.floor(pred_x), math.floor(pred_y))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/cua_agent/loops/uiins.py` around lines 167 - 171, The
function currently multiplies pred_x/pred_y from parse_coordinates and always
returns floored coordinates even when parse failed (parse_coordinates returned
an invalid sentinel like (-1, -1)); update the logic in the function containing
the parse_coordinates call to detect an invalid parse result (e.g., check for
None or the sentinel values returned by parse_coordinates) before scaling, and
return None immediately if parsing failed so the method honors its "return None
on prediction failure" contract; reference the parse_coordinates call and the
pred_x/pred_y handling (and scale_x/scale_y usage) when applying this guard.

"rich>=13.7.1",
"python-dotenv>=1.0.1",
"cua-core>=0.1.18,<0.2.0",
"cua-core>=0.3.0,<0.4.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Check declared cua-agent package version:"
fd -i pyproject.toml | xargs rg -n '^name = "cua-agent"$|^version = "'

echo
echo "Check where cua-agent>=0.8.0 is required:"
fd -i pyproject.toml | xargs rg -n 'cua-agent>=0\.8\.0'

Repository: trycua/cua

Length of output: 2756


cua-agent version must be bumped to 0.8.0 or higher.

The package declares version = "0.7.39" but downstream packages (cua-sandbox and cua-bench) require cua-agent>=0.8.0. Publishing at 0.7.39 will cause dependency resolution failures.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/agent/pyproject.toml` at line 22, The package manifest currently
pins the package version at version = "0.7.39" which conflicts with downstream
requirements; update the package version string for cua-agent to at least
"0.8.0" (e.g., change version = "0.7.39" to version = "0.8.0") in pyproject.toml
and ensure any related metadata (package __version__ if present) is kept in sync
so consumers requiring cua-agent>=0.8.0 will resolve correctly.


try:
from agent import ComputerAgent
from cua_agent import ComputerAgent

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Complete the namespace migration in this module.

The file still imports old package paths at Line 282 (core.http) and Line 985 (agent.computers). Once old namespaces are removed, this will break auth and /responses at runtime.

🔧 Proposed fix
-            from core.http import cua_version_headers
+            from cua_core.http import cua_version_headers
...
-    from agent.computers import AsyncComputerHandler  # runtime-checkable Protocol
+    from cua_agent.computers import AsyncComputerHandler  # runtime-checkable Protocol
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/computer-server/computer_server/main.py` at line 44, This module
still imports the old namespaces (core.http and agent.computers) which breaks
auth and the /responses routes; update the import lines so they reference the
migrated package paths used elsewhere (e.g., import the HTTP utilities and types
from the new cua_agent namespace and import ComputerAgent from the new agent
package) and adjust any local references if the module path or symbol names
changed; specifically replace usages/imports of core.http and agent.computers
with their new equivalents used by ComputerAgent (ensure auth handlers and the
/responses route reference the updated modules), and run a quick grep for
core.http and agent.computers to confirm all imports/usages are migrated.

dependencies = [
"mcp>=1.6.0,<2.0.0",
"cua-agent[all]>=0.4.0,<0.5.0",
"cua-agent[all]>=0.8.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Find legacy mcp-server import usage"
rg -n --type=py -C2 '\bfrom\s+agent\s+import\s+ComputerAgent\b' libs/python/mcp-server

echo "2) Confirm canonical ComputerAgent export under renamed package"
rg -n --type=py -C2 'from \.agent import ComputerAgent|__all__' libs/python/agent/cua_agent/__init__.py

echo "3) Check whether legacy top-level package shim still exists in this repo"
fd -HI '^agent$' libs/python/agent

Repository: trycua/cua

Length of output: 832


Migrate mcp-server imports before bumping cua-agent to >=0.8.0.

libs/python/mcp-server/mcp_server/server.py line 38 imports from agent import ComputerAgent, which no longer exists under the legacy namespace. The canonical export is now at cua_agent.agent.ComputerAgent. Either update the mcp-server imports to use cua_agent or keep the version constraint until the migration completes in this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/python/mcp-server/pyproject.toml` at line 16, Import resolution breaks
because code still uses the legacy module export "from agent import
ComputerAgent" while the package now exposes the class as
cua_agent.agent.ComputerAgent; update the import in mcp-server server module to
"from cua_agent.agent import ComputerAgent" (and similarly migrate any other
"from agent ..." imports) or else revert the pyproject bump (keep
"cua-agent[all]<0.8.0") until the migration is complete so the existing imports
remain valid.

Comment thread scripts/playground.sh
Comment on lines +259 to +260
from cua_agent import ComputerAgent, LLM, AgentLoop, LLMProvider
from cua_agent.ui.gradio.ui_components import create_gradio_ui

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Checking generated imports in scripts/playground.sh..."
rg -n 'from cua_agent import ComputerAgent, LLM, AgentLoop, LLMProvider' scripts/playground.sh || true

echo
echo "Inspecting cua_agent package namespace definition..."
sed -n '1,120p' libs/python/agent/cua_agent/__init__.py

echo
echo "Searching for direct top-level bindings for LLM/AgentLoop/LLMProvider in __init__.py..."
rg -n '\b(LLM|AgentLoop|LLMProvider|__getattr__)\b' libs/python/agent/cua_agent/__init__.py || true

echo
echo "Expected: import line exists in playground.sh, but no LLM/AgentLoop/LLMProvider binding in cua_agent/__init__.py."

Repository: trycua/cua

Length of output: 1754


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full size of cua_agent/__init__.py ==="
wc -l libs/python/agent/cua_agent/__init__.py

echo
echo "=== Full content of cua_agent/__init__.py ==="
cat -n libs/python/agent/cua_agent/__init__.py

echo
echo "=== Search for LLM definition in cua_agent package ==="
rg -r 'class LLM|def LLM' libs/python/agent/cua_agent/ || echo "No matches found"

echo
echo "=== Search for AgentLoop definition in cua_agent package ==="
rg -r 'class AgentLoop|def AgentLoop' libs/python/agent/cua_agent/ || echo "No matches found"

echo
echo "=== Search for LLMProvider definition in cua_agent package ==="
rg -r 'class LLMProvider|def LLMProvider' libs/python/agent/cua_agent/ || echo "No matches found"

Repository: trycua/cua

Length of output: 2012


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check what symbols are used from the problematic import in run_demo.py ==="
# Extract the generated run_demo.py content around the imports and uses
rg -A 50 'from cua_agent import ComputerAgent, LLM, AgentLoop, LLMProvider' scripts/playground.sh | head -100

echo
echo "=== Search for actual usage of LLM, AgentLoop, LLMProvider in playground.sh ==="
rg '\b(LLM|AgentLoop|LLMProvider)\b' scripts/playground.sh || echo "No usage found"

echo
echo "=== Check if liteLLM or similar packages are available ==="
fd -t f '.*requirements.*\.txt' libs/python/agent/ | head -5 | xargs cat || echo "No requirements files found"

Repository: trycua/cua

Length of output: 3313


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for LLM/AgentLoop/LLMProvider definitions anywhere in repo ==="
rg -l '\bLLM\b|\bAgentLoop\b|\bLLMProvider\b' --type python . | head -20 || echo "No matches"

echo
echo "=== Check what's actually imported and used in generated run_demo.py code ==="
# Extract just the relevant sections more carefully
rg -B 5 -A 100 'from cua_agent import ComputerAgent, LLM, AgentLoop, LLMProvider' scripts/playground.sh | grep -E '(^[0-9]+-import|^[0-9]+-from|^[0-9]+-[A-Z]|EOF|LLM|AgentLoop|LLMProvider)' | head -50 || true

echo
echo "=== Confirm: These imports are NOT used in the generated code ==="
echo "The only symbols used in run_demo.py are:"
echo "  - ComputerAgent (imported from cua_agent)"
echo "  - create_gradio_ui (imported from cua_agent.ui.gradio.ui_components)"
echo "  - Standard library modules"

Repository: trycua/cua

Length of output: 697


Remove unused imports that will cause startup failure.

Lines 259 and 294 in the generated run_demo.py import LLM, AgentLoop, and LLMProvider from cua_agent, but these symbols do not exist in the package and are never used in the generated code. The import statement will fail at runtime and block playground startup.

Proposed fix
-from cua_agent import ComputerAgent, LLM, AgentLoop, LLMProvider
+from cua_agent import ComputerAgent
 from cua_agent.ui.gradio.ui_components import create_gradio_ui

Apply the same change in both generated run_demo.py templates (cloud and local branches).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/playground.sh` around lines 259 - 260, The import line in the
generated run_demo.py templates incorrectly includes non-existent and unused
symbols LLM, AgentLoop, and LLMProvider from cua_agent; remove those three names
so the import reads only import ComputerAgent (leave the separate from
cua_agent.ui.gradio.ui_components import create_gradio_ui as-is), and apply this
same change to both generated run_demo.py templates (cloud and local branches)
to prevent startup import failures.

Fix 24 files that still imported from the old 'agent' and 'core'
namespaces after the initial rename commit, including two runtime-critical
missed imports in computer_server/main.py (core.http at line 282 and
agent.computers at line 985), blog examples, tests, cua-cli, cua-sandbox,
mcp-server, computer library, and cua-bench agent files.

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

Copy link
Copy Markdown
Contributor

📦 Publishable packages changed

  • pypi/agent
  • pypi/bench
  • pypi/cli
  • pypi/computer
  • pypi/computer-server
  • pypi/core
  • pypi/mcp-server

Add release:<service> labels to auto-release on merge (+ optional bump:minor or bump:major, default is patch).
Or add no-release to skip.

Ensures the metapackage requires cua-sandbox with the cua_core namespace
migration (0.1.11+).

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

Copy link
Copy Markdown
Contributor

📦 Publishable packages changed

  • pypi/agent
  • pypi/bench
  • pypi/cli
  • pypi/computer
  • pypi/computer-server
  • pypi/core
  • pypi/mcp-server

Add release:<service> labels to auto-release on merge (+ optional bump:minor or bump:major, default is patch).
Or add no-release to skip.

@ddupont808
ddupont808 merged commit f13f728 into main Apr 15, 2026
11 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants