This is page 2 of 20. Use http://codebase.md/trycua/cua?page={x} to view the full context.
# Directory Structure
```
├── .cursorignore
├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github
│ ├── FUNDING.yml
│ ├── scripts
│ │ ├── get_pyproject_version.py
│ │ └── tests
│ │ ├── __init__.py
│ │ ├── README.md
│ │ └── test_get_pyproject_version.py
│ └── workflows
│ ├── bump-version.yml
│ ├── ci-lume.yml
│ ├── docker-publish-cua-linux.yml
│ ├── docker-publish-cua-windows.yml
│ ├── docker-publish-kasm.yml
│ ├── docker-publish-xfce.yml
│ ├── docker-reusable-publish.yml
│ ├── link-check.yml
│ ├── lint.yml
│ ├── npm-publish-cli.yml
│ ├── npm-publish-computer.yml
│ ├── npm-publish-core.yml
│ ├── publish-lume.yml
│ ├── pypi-publish-agent.yml
│ ├── pypi-publish-computer-server.yml
│ ├── pypi-publish-computer.yml
│ ├── pypi-publish-core.yml
│ ├── pypi-publish-mcp-server.yml
│ ├── pypi-publish-som.yml
│ ├── pypi-reusable-publish.yml
│ ├── python-tests.yml
│ ├── test-cua-models.yml
│ └── test-validation-script.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .prettierignore
├── .prettierrc.yaml
├── .vscode
│ ├── docs.code-workspace
│ ├── extensions.json
│ ├── launch.json
│ ├── libs-ts.code-workspace
│ ├── lume.code-workspace
│ ├── lumier.code-workspace
│ ├── py.code-workspace
│ └── settings.json
├── blog
│ ├── app-use.md
│ ├── assets
│ │ ├── composite-agents.png
│ │ ├── docker-ubuntu-support.png
│ │ ├── hack-booth.png
│ │ ├── hack-closing-ceremony.jpg
│ │ ├── hack-cua-ollama-hud.jpeg
│ │ ├── hack-leaderboard.png
│ │ ├── hack-the-north.png
│ │ ├── hack-winners.jpeg
│ │ ├── hack-workshop.jpeg
│ │ ├── hud-agent-evals.png
│ │ └── trajectory-viewer.jpeg
│ ├── bringing-computer-use-to-the-web.md
│ ├── build-your-own-operator-on-macos-1.md
│ ├── build-your-own-operator-on-macos-2.md
│ ├── cloud-windows-ga-macos-preview.md
│ ├── composite-agents.md
│ ├── computer-use-agents-for-growth-hacking.md
│ ├── cua-hackathon.md
│ ├── cua-playground-preview.md
│ ├── cua-vlm-router.md
│ ├── hack-the-north.md
│ ├── hud-agent-evals.md
│ ├── human-in-the-loop.md
│ ├── introducing-cua-cli.md
│ ├── introducing-cua-cloud-containers.md
│ ├── lume-to-containerization.md
│ ├── neurips-2025-cua-papers.md
│ ├── sandboxed-python-execution.md
│ ├── training-computer-use-models-trajectories-1.md
│ ├── trajectory-viewer.md
│ ├── ubuntu-docker-support.md
│ └── windows-sandbox.md
├── CONTRIBUTING.md
├── Development.md
├── Dockerfile
├── docs
│ ├── .env.example
│ ├── .gitignore
│ ├── content
│ │ └── docs
│ │ ├── agent-sdk
│ │ │ ├── agent-loops.mdx
│ │ │ ├── benchmarks
│ │ │ │ ├── index.mdx
│ │ │ │ ├── interactive.mdx
│ │ │ │ ├── introduction.mdx
│ │ │ │ ├── meta.json
│ │ │ │ ├── osworld-verified.mdx
│ │ │ │ ├── screenspot-pro.mdx
│ │ │ │ └── screenspot-v2.mdx
│ │ │ ├── callbacks
│ │ │ │ ├── agent-lifecycle.mdx
│ │ │ │ ├── cost-saving.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ ├── logging.mdx
│ │ │ │ ├── meta.json
│ │ │ │ ├── pii-anonymization.mdx
│ │ │ │ └── trajectories.mdx
│ │ │ ├── chat-history.mdx
│ │ │ ├── custom-tools.mdx
│ │ │ ├── customizing-computeragent.mdx
│ │ │ ├── integrations
│ │ │ │ ├── hud.mdx
│ │ │ │ ├── meta.json
│ │ │ │ └── observability.mdx
│ │ │ ├── mcp-server
│ │ │ │ ├── client-integrations.mdx
│ │ │ │ ├── configuration.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ ├── installation.mdx
│ │ │ │ ├── llm-integrations.mdx
│ │ │ │ ├── meta.json
│ │ │ │ ├── tools.mdx
│ │ │ │ └── usage.mdx
│ │ │ ├── message-format.mdx
│ │ │ ├── meta.json
│ │ │ ├── migration-guide.mdx
│ │ │ ├── prompt-caching.mdx
│ │ │ ├── supported-agents
│ │ │ │ ├── composed-agents.mdx
│ │ │ │ ├── computer-use-agents.mdx
│ │ │ │ ├── grounding-models.mdx
│ │ │ │ ├── human-in-the-loop.mdx
│ │ │ │ └── meta.json
│ │ │ ├── supported-model-providers
│ │ │ │ ├── cua-vlm-router.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ └── local-models.mdx
│ │ │ ├── telemetry.mdx
│ │ │ └── usage-tracking.mdx
│ │ ├── cli-playbook
│ │ │ ├── commands.mdx
│ │ │ ├── index.mdx
│ │ │ └── meta.json
│ │ ├── computer-sdk
│ │ │ ├── cloud-vm-management.mdx
│ │ │ ├── commands.mdx
│ │ │ ├── computer-server
│ │ │ │ ├── Commands.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ ├── meta.json
│ │ │ │ ├── REST-API.mdx
│ │ │ │ └── WebSocket-API.mdx
│ │ │ ├── computer-ui.mdx
│ │ │ ├── computers.mdx
│ │ │ ├── custom-computer-handlers.mdx
│ │ │ ├── meta.json
│ │ │ ├── sandboxed-python.mdx
│ │ │ └── tracing-api.mdx
│ │ ├── example-usecases
│ │ │ ├── form-filling.mdx
│ │ │ ├── gemini-complex-ui-navigation.mdx
│ │ │ ├── meta.json
│ │ │ ├── post-event-contact-export.mdx
│ │ │ └── windows-app-behind-vpn.mdx
│ │ ├── get-started
│ │ │ ├── meta.json
│ │ │ └── quickstart.mdx
│ │ ├── index.mdx
│ │ ├── macos-vm-cli-playbook
│ │ │ ├── lume
│ │ │ │ ├── cli-reference.mdx
│ │ │ │ ├── faq.md
│ │ │ │ ├── http-api.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ ├── installation.mdx
│ │ │ │ ├── meta.json
│ │ │ │ └── prebuilt-images.mdx
│ │ │ ├── lumier
│ │ │ │ ├── building-lumier.mdx
│ │ │ │ ├── docker-compose.mdx
│ │ │ │ ├── docker.mdx
│ │ │ │ ├── index.mdx
│ │ │ │ ├── installation.mdx
│ │ │ │ └── meta.json
│ │ │ └── meta.json
│ │ └── meta.json
│ ├── next.config.mjs
│ ├── package-lock.json
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── postcss.config.mjs
│ ├── public
│ │ └── img
│ │ ├── agent_gradio_ui.png
│ │ ├── agent.png
│ │ ├── bg-dark.jpg
│ │ ├── bg-light.jpg
│ │ ├── cli.png
│ │ ├── computer.png
│ │ ├── grounding-with-gemini3.gif
│ │ ├── hero.png
│ │ ├── laminar_trace_example.png
│ │ ├── som_box_threshold.png
│ │ └── som_iou_threshold.png
│ ├── README.md
│ ├── source.config.ts
│ ├── src
│ │ ├── app
│ │ │ ├── (home)
│ │ │ │ ├── [[...slug]]
│ │ │ │ │ └── page.tsx
│ │ │ │ └── layout.tsx
│ │ │ ├── api
│ │ │ │ ├── posthog
│ │ │ │ │ └── [...path]
│ │ │ │ │ └── route.ts
│ │ │ │ └── search
│ │ │ │ └── route.ts
│ │ │ ├── favicon.ico
│ │ │ ├── global.css
│ │ │ ├── layout.config.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── llms.mdx
│ │ │ │ └── [[...slug]]
│ │ │ │ └── route.ts
│ │ │ ├── llms.txt
│ │ │ │ └── route.ts
│ │ │ ├── robots.ts
│ │ │ └── sitemap.ts
│ │ ├── assets
│ │ │ ├── discord-black.svg
│ │ │ ├── discord-white.svg
│ │ │ ├── logo-black.svg
│ │ │ └── logo-white.svg
│ │ ├── components
│ │ │ ├── analytics-tracker.tsx
│ │ │ ├── cookie-consent.tsx
│ │ │ ├── doc-actions-menu.tsx
│ │ │ ├── editable-code-block.tsx
│ │ │ ├── footer.tsx
│ │ │ ├── hero.tsx
│ │ │ ├── iou.tsx
│ │ │ ├── mermaid.tsx
│ │ │ └── page-feedback.tsx
│ │ ├── lib
│ │ │ ├── llms.ts
│ │ │ └── source.ts
│ │ ├── mdx-components.tsx
│ │ └── providers
│ │ └── posthog-provider.tsx
│ └── tsconfig.json
├── examples
│ ├── agent_examples.py
│ ├── agent_ui_examples.py
│ ├── browser_tool_example.py
│ ├── cloud_api_examples.py
│ ├── computer_examples_windows.py
│ ├── computer_examples.py
│ ├── computer_ui_examples.py
│ ├── computer-example-ts
│ │ ├── .env.example
│ │ ├── .gitignore
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── helpers.ts
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── docker_examples.py
│ ├── evals
│ │ ├── hud_eval_examples.py
│ │ └── wikipedia_most_linked.txt
│ ├── pylume_examples.py
│ ├── sandboxed_functions_examples.py
│ ├── som_examples.py
│ ├── tracing_examples.py
│ ├── utils.py
│ └── winsandbox_example.py
├── img
│ ├── agent_gradio_ui.png
│ ├── agent.png
│ ├── cli.png
│ ├── computer.png
│ ├── logo_black.png
│ └── logo_white.png
├── libs
│ ├── kasm
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── src
│ │ └── ubuntu
│ │ └── install
│ │ └── firefox
│ │ ├── custom_startup.sh
│ │ ├── firefox.desktop
│ │ └── install_firefox.sh
│ ├── lume
│ │ ├── .cursorignore
│ │ ├── CONTRIBUTING.md
│ │ ├── Development.md
│ │ ├── img
│ │ │ └── cli.png
│ │ ├── Package.resolved
│ │ ├── Package.swift
│ │ ├── README.md
│ │ ├── resources
│ │ │ └── lume.entitlements
│ │ ├── scripts
│ │ │ ├── build
│ │ │ │ ├── build-debug.sh
│ │ │ │ ├── build-release-notarized.sh
│ │ │ │ └── build-release.sh
│ │ │ └── install.sh
│ │ ├── src
│ │ │ ├── Commands
│ │ │ │ ├── Clone.swift
│ │ │ │ ├── Config.swift
│ │ │ │ ├── Create.swift
│ │ │ │ ├── Delete.swift
│ │ │ │ ├── Get.swift
│ │ │ │ ├── Images.swift
│ │ │ │ ├── IPSW.swift
│ │ │ │ ├── List.swift
│ │ │ │ ├── Logs.swift
│ │ │ │ ├── Options
│ │ │ │ │ └── FormatOption.swift
│ │ │ │ ├── Prune.swift
│ │ │ │ ├── Pull.swift
│ │ │ │ ├── Push.swift
│ │ │ │ ├── Run.swift
│ │ │ │ ├── Serve.swift
│ │ │ │ ├── Set.swift
│ │ │ │ └── Stop.swift
│ │ │ ├── ContainerRegistry
│ │ │ │ ├── ImageContainerRegistry.swift
│ │ │ │ ├── ImageList.swift
│ │ │ │ └── ImagesPrinter.swift
│ │ │ ├── Errors
│ │ │ │ └── Errors.swift
│ │ │ ├── FileSystem
│ │ │ │ ├── Home.swift
│ │ │ │ ├── Settings.swift
│ │ │ │ ├── VMConfig.swift
│ │ │ │ ├── VMDirectory.swift
│ │ │ │ └── VMLocation.swift
│ │ │ ├── LumeController.swift
│ │ │ ├── Main.swift
│ │ │ ├── Server
│ │ │ │ ├── Handlers.swift
│ │ │ │ ├── HTTP.swift
│ │ │ │ ├── Requests.swift
│ │ │ │ ├── Responses.swift
│ │ │ │ └── Server.swift
│ │ │ ├── Utils
│ │ │ │ ├── CommandRegistry.swift
│ │ │ │ ├── CommandUtils.swift
│ │ │ │ ├── Logger.swift
│ │ │ │ ├── NetworkUtils.swift
│ │ │ │ ├── Path.swift
│ │ │ │ ├── ProcessRunner.swift
│ │ │ │ ├── ProgressLogger.swift
│ │ │ │ ├── String.swift
│ │ │ │ └── Utils.swift
│ │ │ ├── Virtualization
│ │ │ │ ├── DarwinImageLoader.swift
│ │ │ │ ├── DHCPLeaseParser.swift
│ │ │ │ ├── ImageLoaderFactory.swift
│ │ │ │ └── VMVirtualizationService.swift
│ │ │ ├── VM
│ │ │ │ ├── DarwinVM.swift
│ │ │ │ ├── LinuxVM.swift
│ │ │ │ ├── VM.swift
│ │ │ │ ├── VMDetails.swift
│ │ │ │ ├── VMDetailsPrinter.swift
│ │ │ │ ├── VMDisplayResolution.swift
│ │ │ │ └── VMFactory.swift
│ │ │ └── VNC
│ │ │ ├── PassphraseGenerator.swift
│ │ │ └── VNCService.swift
│ │ └── tests
│ │ ├── Mocks
│ │ │ ├── MockVM.swift
│ │ │ ├── MockVMVirtualizationService.swift
│ │ │ └── MockVNCService.swift
│ │ ├── VM
│ │ │ └── VMDetailsPrinterTests.swift
│ │ ├── VMTests.swift
│ │ ├── VMVirtualizationServiceTests.swift
│ │ └── VNCServiceTests.swift
│ ├── lumier
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ └── src
│ │ ├── bin
│ │ │ └── entry.sh
│ │ ├── config
│ │ │ └── constants.sh
│ │ ├── hooks
│ │ │ └── on-logon.sh
│ │ └── lib
│ │ ├── utils.sh
│ │ └── vm.sh
│ ├── python
│ │ ├── agent
│ │ │ ├── .bumpversion.cfg
│ │ │ ├── agent
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ ├── adapters
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── cua_adapter.py
│ │ │ │ │ ├── huggingfacelocal_adapter.py
│ │ │ │ │ ├── human_adapter.py
│ │ │ │ │ ├── mlxvlm_adapter.py
│ │ │ │ │ └── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── generic.py
│ │ │ │ │ ├── internvl.py
│ │ │ │ │ ├── opencua.py
│ │ │ │ │ └── qwen2_5_vl.py
│ │ │ │ ├── agent.py
│ │ │ │ ├── callbacks
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── budget_manager.py
│ │ │ │ │ ├── image_retention.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── operator_validator.py
│ │ │ │ │ ├── pii_anonymization.py
│ │ │ │ │ ├── prompt_instructions.py
│ │ │ │ │ ├── telemetry.py
│ │ │ │ │ └── trajectory_saver.py
│ │ │ │ ├── cli.py
│ │ │ │ ├── computers
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── cua.py
│ │ │ │ │ └── custom.py
│ │ │ │ ├── decorators.py
│ │ │ │ ├── human_tool
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── server.py
│ │ │ │ │ └── ui.py
│ │ │ │ ├── integrations
│ │ │ │ │ └── hud
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── agent.py
│ │ │ │ │ └── proxy.py
│ │ │ │ ├── loops
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── anthropic.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── composed_grounded.py
│ │ │ │ │ ├── gelato.py
│ │ │ │ │ ├── gemini.py
│ │ │ │ │ ├── generic_vlm.py
│ │ │ │ │ ├── glm45v.py
│ │ │ │ │ ├── gta1.py
│ │ │ │ │ ├── holo.py
│ │ │ │ │ ├── internvl.py
│ │ │ │ │ ├── model_types.csv
│ │ │ │ │ ├── moondream3.py
│ │ │ │ │ ├── omniparser.py
│ │ │ │ │ ├── openai.py
│ │ │ │ │ ├── opencua.py
│ │ │ │ │ ├── uiins.py
│ │ │ │ │ ├── uitars.py
│ │ │ │ │ └── uitars2.py
│ │ │ │ ├── proxy
│ │ │ │ │ ├── examples.py
│ │ │ │ │ └── handlers.py
│ │ │ │ ├── responses.py
│ │ │ │ ├── tools
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── browser_tool.py
│ │ │ │ ├── types.py
│ │ │ │ └── ui
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ └── gradio
│ │ │ │ ├── __init__.py
│ │ │ │ ├── app.py
│ │ │ │ └── ui_components.py
│ │ │ ├── benchmarks
│ │ │ │ ├── .gitignore
│ │ │ │ ├── contrib.md
│ │ │ │ ├── interactive.py
│ │ │ │ ├── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ └── gta1.py
│ │ │ │ ├── README.md
│ │ │ │ ├── ss-pro.py
│ │ │ │ ├── ss-v2.py
│ │ │ │ └── utils.py
│ │ │ ├── example.py
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_computer_agent.py
│ │ ├── bench-ui
│ │ │ ├── bench_ui
│ │ │ │ ├── __init__.py
│ │ │ │ ├── api.py
│ │ │ │ └── child.py
│ │ │ ├── examples
│ │ │ │ ├── folder_example.py
│ │ │ │ ├── gui
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── logo.svg
│ │ │ │ │ └── styles.css
│ │ │ │ ├── output_overlay.png
│ │ │ │ └── simple_example.py
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ └── tests
│ │ │ └── test_port_detection.py
│ │ ├── computer
│ │ │ ├── .bumpversion.cfg
│ │ │ ├── computer
│ │ │ │ ├── __init__.py
│ │ │ │ ├── computer.py
│ │ │ │ ├── diorama_computer.py
│ │ │ │ ├── helpers.py
│ │ │ │ ├── interface
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── generic.py
│ │ │ │ │ ├── linux.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── logger.py
│ │ │ │ ├── models.py
│ │ │ │ ├── providers
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── cloud
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── provider.py
│ │ │ │ │ ├── docker
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── provider.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── lume
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── provider.py
│ │ │ │ │ ├── lume_api.py
│ │ │ │ │ ├── lumier
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── provider.py
│ │ │ │ │ ├── types.py
│ │ │ │ │ └── winsandbox
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── provider.py
│ │ │ │ │ └── setup_script.ps1
│ │ │ │ ├── tracing_wrapper.py
│ │ │ │ ├── tracing.py
│ │ │ │ ├── ui
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ └── gradio
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── app.py
│ │ │ │ └── utils.py
│ │ │ ├── poetry.toml
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_computer.py
│ │ ├── computer-server
│ │ │ ├── .bumpversion.cfg
│ │ │ ├── computer_server
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ ├── browser.py
│ │ │ │ ├── cli.py
│ │ │ │ ├── diorama
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── diorama_computer.py
│ │ │ │ │ ├── diorama.py
│ │ │ │ │ ├── draw.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ └── safezone.py
│ │ │ │ ├── handlers
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── generic.py
│ │ │ │ │ ├── linux.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── main.py
│ │ │ │ ├── server.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── wallpaper.py
│ │ │ │ └── watchdog.py
│ │ │ ├── examples
│ │ │ │ ├── __init__.py
│ │ │ │ └── usage_example.py
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ ├── run_server.py
│ │ │ ├── test_connection.py
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_server.py
│ │ ├── core
│ │ │ ├── .bumpversion.cfg
│ │ │ ├── core
│ │ │ │ ├── __init__.py
│ │ │ │ └── telemetry
│ │ │ │ ├── __init__.py
│ │ │ │ └── posthog.py
│ │ │ ├── poetry.toml
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_telemetry.py
│ │ ├── mcp-server
│ │ │ ├── .bumpversion.cfg
│ │ │ ├── build-extension.py
│ │ │ ├── CONCURRENT_SESSIONS.md
│ │ │ ├── desktop-extension
│ │ │ │ ├── cua-extension.mcpb
│ │ │ │ ├── desktop_extension.png
│ │ │ │ ├── manifest.json
│ │ │ │ ├── README.md
│ │ │ │ ├── requirements.txt
│ │ │ │ ├── run_server.sh
│ │ │ │ └── setup.py
│ │ │ ├── mcp_server
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ ├── server.py
│ │ │ │ └── session_manager.py
│ │ │ ├── pdm.lock
│ │ │ ├── pyproject.toml
│ │ │ ├── QUICK_TEST_COMMANDS.sh
│ │ │ ├── quick_test_local_option.py
│ │ │ ├── README.md
│ │ │ ├── scripts
│ │ │ │ ├── install_mcp_server.sh
│ │ │ │ └── start_mcp_server.sh
│ │ │ ├── test_mcp_server_local_option.py
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_mcp_server.py
│ │ ├── pylume
│ │ │ └── tests
│ │ │ ├── conftest.py
│ │ │ └── test_pylume.py
│ │ └── som
│ │ ├── .bumpversion.cfg
│ │ ├── LICENSE
│ │ ├── poetry.toml
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── som
│ │ │ ├── __init__.py
│ │ │ ├── detect.py
│ │ │ ├── detection.py
│ │ │ ├── models.py
│ │ │ ├── ocr.py
│ │ │ ├── util
│ │ │ │ └── utils.py
│ │ │ └── visualization.py
│ │ └── tests
│ │ ├── conftest.py
│ │ └── test_omniparser.py
│ ├── qemu-docker
│ │ ├── linux
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ ├── entry.sh
│ │ │ └── vm
│ │ │ ├── image
│ │ │ │ └── README.md
│ │ │ └── setup
│ │ │ ├── install.sh
│ │ │ ├── setup-cua-server.sh
│ │ │ └── setup.sh
│ │ ├── README.md
│ │ └── windows
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ └── src
│ │ ├── entry.sh
│ │ └── vm
│ │ ├── image
│ │ │ └── README.md
│ │ └── setup
│ │ ├── install.bat
│ │ ├── on-logon.ps1
│ │ ├── setup-cua-server.ps1
│ │ ├── setup-utils.psm1
│ │ └── setup.ps1
│ ├── typescript
│ │ ├── .gitignore
│ │ ├── .nvmrc
│ │ ├── agent
│ │ │ ├── examples
│ │ │ │ ├── playground-example.html
│ │ │ │ └── README.md
│ │ │ ├── package.json
│ │ │ ├── README.md
│ │ │ ├── src
│ │ │ │ ├── client.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── tests
│ │ │ │ └── client.test.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── tsdown.config.ts
│ │ │ └── vitest.config.ts
│ │ ├── computer
│ │ │ ├── .editorconfig
│ │ │ ├── .gitattributes
│ │ │ ├── .gitignore
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ ├── README.md
│ │ │ ├── src
│ │ │ │ ├── computer
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── providers
│ │ │ │ │ │ ├── base.ts
│ │ │ │ │ │ ├── cloud.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── interface
│ │ │ │ │ ├── base.ts
│ │ │ │ │ ├── factory.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── linux.ts
│ │ │ │ │ ├── macos.ts
│ │ │ │ │ └── windows.ts
│ │ │ │ └── types.ts
│ │ │ ├── tests
│ │ │ │ ├── computer
│ │ │ │ │ └── cloud.test.ts
│ │ │ │ ├── interface
│ │ │ │ │ ├── factory.test.ts
│ │ │ │ │ ├── index.test.ts
│ │ │ │ │ ├── linux.test.ts
│ │ │ │ │ ├── macos.test.ts
│ │ │ │ │ └── windows.test.ts
│ │ │ │ └── setup.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── tsdown.config.ts
│ │ │ └── vitest.config.ts
│ │ ├── core
│ │ │ ├── .editorconfig
│ │ │ ├── .gitattributes
│ │ │ ├── .gitignore
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ ├── README.md
│ │ │ ├── src
│ │ │ │ ├── index.ts
│ │ │ │ └── telemetry
│ │ │ │ ├── clients
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── posthog.ts
│ │ │ │ └── index.ts
│ │ │ ├── tests
│ │ │ │ └── telemetry.test.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── tsdown.config.ts
│ │ │ └── vitest.config.ts
│ │ ├── cua-cli
│ │ │ ├── .gitignore
│ │ │ ├── .prettierrc
│ │ │ ├── bun.lock
│ │ │ ├── CLAUDE.md
│ │ │ ├── index.ts
│ │ │ ├── package.json
│ │ │ ├── README.md
│ │ │ ├── src
│ │ │ │ ├── auth.ts
│ │ │ │ ├── cli.ts
│ │ │ │ ├── commands
│ │ │ │ │ ├── auth.ts
│ │ │ │ │ └── sandbox.ts
│ │ │ │ ├── config.ts
│ │ │ │ ├── http.ts
│ │ │ │ ├── storage.ts
│ │ │ │ └── util.ts
│ │ │ └── tsconfig.json
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── pnpm-workspace.yaml
│ │ └── README.md
│ └── xfce
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Development.md
│ ├── Dockerfile
│ ├── Dockerfile.dev
│ ├── README.md
│ └── src
│ ├── scripts
│ │ ├── resize-display.sh
│ │ ├── start-computer-server.sh
│ │ ├── start-novnc.sh
│ │ ├── start-vnc.sh
│ │ └── xstartup.sh
│ ├── supervisor
│ │ └── supervisord.conf
│ └── xfce-config
│ ├── helpers.rc
│ ├── xfce4-power-manager.xml
│ └── xfce4-session.xml
├── LICENSE.md
├── Makefile
├── notebooks
│ ├── agent_nb.ipynb
│ ├── blog
│ │ ├── build-your-own-operator-on-macos-1.ipynb
│ │ └── build-your-own-operator-on-macos-2.ipynb
│ ├── composite_agents_docker_nb.ipynb
│ ├── computer_nb.ipynb
│ ├── computer_server_nb.ipynb
│ ├── customizing_computeragent.ipynb
│ ├── eval_osworld.ipynb
│ ├── ollama_nb.ipynb
│ ├── README.md
│ ├── sota_hackathon_cloud.ipynb
│ └── sota_hackathon.ipynb
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── pyproject.toml
├── pyrightconfig.json
├── README.md
├── scripts
│ ├── install-cli.ps1
│ ├── install-cli.sh
│ ├── playground-docker.sh
│ ├── playground.sh
│ ├── run-docker-dev.sh
│ └── typescript-typecheck.js
├── TESTING.md
├── tests
│ ├── agent_loop_testing
│ │ ├── agent_test.py
│ │ └── README.md
│ ├── pytest.ini
│ ├── shell_cmd.py
│ ├── test_files.py
│ ├── test_mcp_server_session_management.py
│ ├── test_mcp_server_streaming.py
│ ├── test_shell_bash.py
│ ├── test_telemetry.py
│ ├── test_tracing.py
│ ├── test_venv.py
│ └── test_watchdog.py
└── uv.lock
```
# Files
--------------------------------------------------------------------------------
/libs/typescript/cua-cli/src/config.ts:
--------------------------------------------------------------------------------
```typescript
export const WEBSITE_URL =
Bun.env.CUA_WEBSITE_URL?.replace(/\/$/, '') || 'https://cua.ai';
export const API_BASE =
Bun.env.CUA_API_BASE?.replace(/\/$/, '') || 'https://api.cua.ai';
export const AUTH_PAGE = `${WEBSITE_URL}/cli-auth`;
export const CALLBACK_HOST = '127.0.0.1';
export function getConfigDir(): string {
const home = Bun.env.HOME || Bun.env.USERPROFILE || '.';
const dir = `${home}/.cua`;
try {
Bun.spawnSync(['mkdir', '-p', dir]);
} catch {}
return dir;
}
export function getDbPath(): string {
return `${getConfigDir()}/cli.sqlite`;
}
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/mcp_server/__init__.py:
--------------------------------------------------------------------------------
```python
"""MCP Server for Computer-Use Agent (CUA)."""
import os
import sys
# Add detailed debugging at import time
with open("/tmp/mcp_server_debug.log", "w") as f:
f.write(f"Python executable: {sys.executable}\n")
f.write(f"Python version: {sys.version}\n")
f.write(f"Working directory: {os.getcwd()}\n")
f.write(f"Python path:\n{chr(10).join(sys.path)}\n")
f.write("Environment variables:\n")
for key, value in os.environ.items():
f.write(f"{key}={value}\n")
from .server import main, server
__version__ = "0.1.0"
__all__ = ["server", "main"]
```
--------------------------------------------------------------------------------
/examples/computer-example-ts/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"target": "esnext",
"lib": ["es2023"],
"moduleDetection": "force",
"module": "preserve",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"types": ["node"],
"allowSyntheticDefaultImports": true,
"strict": true,
"noUnusedLocals": true,
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"outDir": "build"
},
"include": ["src"]
}
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
name = "cua-mcp-server"
description = "MCP Server for Computer-Use Agent (CUA)"
readme = "README.md"
requires-python = ">=3.12,<3.14"
version = "0.1.15"
authors = [
{name = "TryCua", email = "[email protected]"}
]
dependencies = [
"mcp>=1.6.0,<2.0.0",
"cua-agent[all]>=0.4.0,<0.5.0",
"cua-computer>=0.4.0,<0.5.0",
]
[project.scripts]
cua-mcp-server = "mcp_server.server:main"
[tool.pdm]
distribution = true
[tool.pdm.dev-dependencies]
dev = [
"black>=23.9.1",
"ruff>=0.0.292",
]
```
--------------------------------------------------------------------------------
/libs/python/som/tests/conftest.py:
--------------------------------------------------------------------------------
```python
"""Pytest configuration for som tests.
This module provides test fixtures for the som (Set-of-Mark) package.
The som package depends on heavy ML models and will skip tests if not available.
"""
from unittest.mock import Mock, patch
import pytest
@pytest.fixture
def mock_torch():
with patch("torch.load") as mock_load:
mock_load.return_value = Mock()
yield mock_load
@pytest.fixture
def mock_icon_detector():
with patch("omniparser.IconDetector") as mock_detector:
instance = Mock()
mock_detector.return_value = instance
yield instance
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/benchmarks/screenspot-v2.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: ScreenSpot-v2
description: Standard resolution GUI grounding benchmark
---
ScreenSpot-v2 is a benchmark for evaluating click prediction accuracy on standard resolution GUI screenshots.
## Usage
```bash
# Run the benchmark
cd libs/python/agent/benchmarks
python ss-v2.py
# Run with custom sample limit
python ss-v2.py --samples 100
```
## Results
| Model | Accuracy | Failure Rate | Samples |
| ----------- | -------- | ------------ | ------- |
| Coming Soon | - | - | - |
Results will be populated after running benchmarks with various models.
```
--------------------------------------------------------------------------------
/examples/computer-example-ts/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "computer-example-ts",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "index.js",
"scripts": {
"dev": "tsx watch src/index.ts",
"start": "tsx src/index.ts",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"keywords": [],
"author": "",
"license": "MIT",
"packageManager": "[email protected]",
"dependencies": {
"@trycua/computer": "^0.1.3",
"dotenv": "^16.5.0",
"openai": "^5.7.0"
},
"devDependencies": {
"@types/node": "^22.15.33",
"tsx": "^4.20.3",
"typescript": "^5.8.3"
}
}
```
--------------------------------------------------------------------------------
/libs/qemu-docker/linux/src/vm/setup/install.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# OEM Installation Entry Point for Linux
# This script is called by the OEM systemd service on first boot
set -e
SCRIPT_DIR="/opt/oem"
LOG_FILE="$SCRIPT_DIR/setup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== Starting OEM Setup ==="
# Run main setup script
if [ -f "$SCRIPT_DIR/setup.sh" ]; then
log "Running setup.sh..."
bash "$SCRIPT_DIR/setup.sh" 2>&1 | tee -a "$LOG_FILE"
log "setup.sh completed with exit code: $?"
else
log "ERROR: setup.sh not found at $SCRIPT_DIR/setup.sh"
exit 1
fi
log "=== OEM Setup Completed ==="
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/benchmarks/screenspot-pro.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: ScreenSpot-Pro
description: High-resolution GUI grounding benchmark
---
ScreenSpot-Pro is a benchmark for evaluating click prediction accuracy on high-resolution GUI screenshots with complex layouts.
## Usage
```bash
# Run the benchmark
cd libs/python/agent/benchmarks
python ss-pro.py
# Run with custom sample limit
python ss-pro.py --samples 50
```
## Results
| Model | Accuracy | Failure Rate | Samples |
| ----------- | -------- | ------------ | ------- |
| Coming Soon | - | - | - |
Results will be populated after running benchmarks with various models.
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Stop.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Stop: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Stop a virtual machine"
)
@Argument(help: "Name of the virtual machine", completion: .custom(completeVMName))
var name: String
@Option(name: .customLong("storage"), help: "VM storage location to use or direct path to VM location")
var storage: String?
init() {
}
@MainActor
func run() async throws {
let vmController = LumeController()
try await vmController.stopVM(name: name, storage: storage)
}
}
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/loops/__init__.py:
--------------------------------------------------------------------------------
```python
"""
Agent loops for agent
"""
# Import the loops to register them
from . import (
anthropic,
composed_grounded,
gelato,
gemini,
generic_vlm,
glm45v,
gta1,
holo,
internvl,
moondream3,
omniparser,
openai,
opencua,
uiins,
uitars,
uitars2,
)
__all__ = [
"anthropic",
"composed_grounded",
"gelato",
"gemini",
"generic_vlm",
"glm45v",
"gta1",
"holo",
"internvl",
"moondream3",
"omniparser",
"openai",
"opencua",
"uiins",
"uitars",
"uitars2",
]
```
--------------------------------------------------------------------------------
/libs/typescript/agent/src/index.ts:
--------------------------------------------------------------------------------
```typescript
// Export the main AgentClient class as default
export { AgentClient as default } from './client.js';
// Also export as named export for flexibility
export { AgentClient } from './client.js';
// Export types for TypeScript users
export type {
AgentRequest,
AgentResponse,
AgentMessage,
UserMessage,
AssistantMessage,
ReasoningMessage,
ComputerCallMessage,
ComputerCallOutputMessage,
OutputContent,
SummaryContent,
InputContent,
ComputerAction,
ClickAction,
TypeAction,
KeyPressAction,
ScrollAction,
WaitAction,
Usage,
ConnectionType,
AgentClientOptions,
} from './types';
```
--------------------------------------------------------------------------------
/libs/python/pylume/tests/conftest.py:
--------------------------------------------------------------------------------
```python
"""Pytest configuration for pylume tests.
This module provides test fixtures for the pylume package.
Note: This package has macOS-specific dependencies and will skip tests
if the required modules are not available.
"""
from unittest.mock import Mock, patch
import pytest
@pytest.fixture
def mock_subprocess():
with patch("subprocess.run") as mock_run:
mock_run.return_value = Mock(returncode=0, stdout="", stderr="")
yield mock_run
@pytest.fixture
def mock_requests():
with patch("requests.get") as mock_get, patch("requests.post") as mock_post:
yield {"get": mock_get, "post": mock_post}
```
--------------------------------------------------------------------------------
/libs/typescript/computer/src/computer/types.ts:
--------------------------------------------------------------------------------
```typescript
import type { OSType, ScreenSize } from '../types';
/**
* Display configuration for the computer.
*/
export interface Display extends ScreenSize {
scale_factor?: number;
}
/**
* Computer configuration model.
*/
export interface BaseComputerConfig {
/**
* The VM name
* @default ""
*/
name: string;
/**
* The operating system type ('macos', 'windows', or 'linux')
* @default "macos"
*/
osType: OSType;
}
export interface CloudComputerConfig extends BaseComputerConfig {
/**
* Optional API key for cloud providers
*/
apiKey: string;
}
export enum VMProviderType {
CLOUD = 'cloud',
}
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/benchmarks/interactive.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Interactive Tool
description: Real-time testing and visualization tool for GUI grounding models
---
This tool allows you to test multiple models interactively by providing natural language instructions. It automatically captures screenshots and tests all configured models sequentially, providing immediate feedback and visual results.
## Usage
```bash
# Start the interactive tool
cd libs/python/agent/benchmarks
python interactive.py
```
## Commands
- **Type instruction**: Screenshot + test all models
- **`screenshot`**: Take screenshot without prediction
- **`models`**: List available models
- **`quit`/`exit`**: Exit the tool
```
--------------------------------------------------------------------------------
/examples/agent_ui_examples.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Simple example script for the Computer-Use Agent Gradio UI.
This script launches the advanced Gradio UI for the Computer-Use Agent
with full model selection and configuration options.
It can be run directly from the command line.
"""
from utils import load_dotenv_files
load_dotenv_files()
# Import the create_gradio_ui function
from agent.ui.gradio.ui_components import create_gradio_ui
if __name__ == "__main__":
print("Launching Computer-Use Agent Gradio UI with advanced features...")
app = create_gradio_ui()
app.launch(
share=False,
server_name="0.0.0.0",
server_port=7860,
)
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/mcp-server/index.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: MCP Server
description: Run Cua agents through Claude Desktop and other MCP clients
---
The MCP Server exposes Cua agents as tools for [Model Context Protocol](https://modelcontextprotocol.io/) clients like Claude Desktop. This lets you ask Claude to perform computer tasks directly from the chat interface.
```bash
pip install cua-mcp-server
```
## Key Features
- **Claude Desktop integration** - Use Cua agents directly in Claude's chat
- **Multi-client support** - Concurrent sessions with automatic resource management
- **Progress reporting** - Real-time updates during task execution
- **VM safety** - Runs in sandboxed VMs by default
```
--------------------------------------------------------------------------------
/libs/python/core/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
name = "cua-core"
version = "0.1.9"
description = "Core functionality for Cua including telemetry and shared utilities"
readme = "README.md"
authors = [
{ name = "TryCua", email = "[email protected]" }
]
dependencies = [
"pydantic>=2.0.0",
"httpx>=0.24.0",
"posthog>=3.20.0"
]
requires-python = ">=3.12,<3.14"
[tool.pdm]
distribution = true
[tool.pdm.build]
includes = ["core/"]
source-includes = ["tests/", "README.md", "LICENSE"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = "test_*.py"
[dependency-groups]
dev = [
"pytest>=8.3.5",
]
```
--------------------------------------------------------------------------------
/docs/source.config.ts:
--------------------------------------------------------------------------------
```typescript
import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';
import { z } from 'zod';
// You can customise Zod schemas for frontmatter and `meta.json` here
// see https://fumadocs.vercel.app/docs/mdx/collections#define-docs
export const docs = defineDocs({
docs: {
schema: frontmatterSchema.extend({
macos: z.boolean().optional(),
windows: z.boolean().optional(),
linux: z.boolean().optional(),
pypi: z.string().optional(),
npm: z.string().optional(),
github: z.array(z.string()).optional(),
}),
},
meta: {
schema: metaSchema,
},
});
export default defineConfig({
mdxOptions: {
// MDX options
},
});
```
--------------------------------------------------------------------------------
/libs/lume/src/Virtualization/ImageLoaderFactory.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
/// Protocol defining a factory for creating image loaders based on the image type
protocol ImageLoaderFactory {
/// Creates an appropriate ImageLoader based on the image path or type
func createImageLoader() -> ImageLoader
}
/// Default implementation of ImageLoaderFactory that creates appropriate loaders based on image type
final class DefaultImageLoaderFactory: ImageLoaderFactory {
func createImageLoader() -> ImageLoader {
// For now, we only support Darwin images
// In the future, this can be extended to support other OS types
// by analyzing the image path or having explicit OS type parameter
return DarwinImageLoader()
}
}
```
--------------------------------------------------------------------------------
/libs/typescript/cua-cli/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}
```
--------------------------------------------------------------------------------
/.github/workflows/test-validation-script.yml:
--------------------------------------------------------------------------------
```yaml
name: Test valididation script
on:
pull_request:
paths:
- ".github/scripts/**"
- ".github/workflows/test-scripts.yml"
push:
branches:
- main
paths:
- ".github/scripts/**"
- ".github/workflows/test-scripts.yml"
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest toml
- name: Run tests
run: |
cd .github/scripts
pytest tests/ -v
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/callbacks/__init__.py:
--------------------------------------------------------------------------------
```python
"""
Callback system for ComputerAgent preprocessing and postprocessing hooks.
"""
from .base import AsyncCallbackHandler
from .budget_manager import BudgetManagerCallback
from .image_retention import ImageRetentionCallback
from .logging import LoggingCallback
from .operator_validator import OperatorNormalizerCallback
from .prompt_instructions import PromptInstructionsCallback
from .telemetry import TelemetryCallback
from .trajectory_saver import TrajectorySaverCallback
__all__ = [
"AsyncCallbackHandler",
"ImageRetentionCallback",
"LoggingCallback",
"TrajectorySaverCallback",
"BudgetManagerCallback",
"TelemetryCallback",
"OperatorNormalizerCallback",
"PromptInstructionsCallback",
]
```
--------------------------------------------------------------------------------
/docs/content/docs/macos-vm-cli-playbook/lumier/installation.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Installation
---
Before using Lumier, make sure you have:
1. **Docker for Apple Silicon** - download it [here](https://desktop.docker.com/mac/main/arm64/Docker.dmg) and follow the installation instructions.
2. **Lume** - This is the virtualization CLI that powers Lumier. Install it with this command:
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/lume/scripts/install.sh)"
```
After installation, Lume runs as a background service and listens on port 7777. This service allows Lumier to create and manage virtual machines. If port 7777 is already in use on your system, you can specify a different port with the `--port` option when running the `install.sh` script.
```
--------------------------------------------------------------------------------
/.github/workflows/docker-publish-xfce.yml:
--------------------------------------------------------------------------------
```yaml
name: Build and Publish CUA XFCE Container
on:
push:
branches:
- main
tags:
- "docker-xfce-v*.*.*"
paths:
- "libs/xfce/**"
- ".github/workflows/docker-publish-xfce.yml"
- ".github/workflows/docker-reusable-publish.yml"
pull_request:
paths:
- "libs/xfce/**"
- ".github/workflows/docker-publish-xfce.yml"
- ".github/workflows/docker-reusable-publish.yml"
jobs:
publish:
uses: ./.github/workflows/docker-reusable-publish.yml
with:
image_name: cua-xfce
context_dir: libs/xfce
dockerfile_path: Dockerfile
tag_prefix: docker-xfce-v
docker_hub_org: trycua
secrets:
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
```
--------------------------------------------------------------------------------
/.github/workflows/docker-publish-kasm.yml:
--------------------------------------------------------------------------------
```yaml
name: Build and Publish CUA Ubuntu Container
on:
push:
branches:
- main
tags:
- "docker-kasm-v*.*.*"
paths:
- "libs/kasm/**"
- ".github/workflows/docker-publish-kasm.yml"
- ".github/workflows/docker-reusable-publish.yml"
pull_request:
paths:
- "libs/kasm/**"
- ".github/workflows/docker-publish-kasm.yml"
- ".github/workflows/docker-reusable-publish.yml"
jobs:
publish:
uses: ./.github/workflows/docker-reusable-publish.yml
with:
image_name: cua-ubuntu
context_dir: libs/kasm
dockerfile_path: Dockerfile
tag_prefix: docker-kasm-v
docker_hub_org: trycua
secrets:
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
```
--------------------------------------------------------------------------------
/libs/lume/src/Utils/NetworkUtils.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
enum NetworkUtils {
/// Checks if an IP address is reachable by sending a ping
/// - Parameter ipAddress: The IP address to check
/// - Returns: true if the IP is reachable, false otherwise
static func isReachable(ipAddress: String) -> Bool {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/sbin/ping")
process.arguments = ["-c", "1", "-t", "1", ipAddress]
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe
do {
try process.run()
process.waitUntilExit()
return process.terminationStatus == 0
} catch {
return false
}
}
}
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/human_tool/__init__.py:
--------------------------------------------------------------------------------
```python
"""
Human-in-the-Loop Completion Tool
This package provides a human-in-the-loop completion system that allows
AI agents to request human assistance for complex decisions or responses.
Components:
- server.py: FastAPI server with completion queue management
- ui.py: Gradio UI for human interaction
- __main__.py: Combined server and UI application
Usage:
# Run the server and UI
python -m agent.human_tool
# Or run components separately
python -m agent.human_tool.server # API server only
python -m agent.human_tool.ui # UI only
"""
from .server import CompletionQueue, completion_queue
from .ui import HumanCompletionUI, create_ui
__all__ = ["CompletionQueue", "completion_queue", "HumanCompletionUI", "create_ui"]
```
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
```json
{
"python-envs.pythonProjects": [],
"python.defaultInterpreterPath": "${workspaceFolder}/.venv",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.fixAll": "explicit"
},
"extensions.ignoreRecommendations": false,
"python.formatting.provider": "black",
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
},
"[javascript][typescript][typescriptreact][javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"ruff.configuration": "${workspaceFolder}/pyproject.toml",
"mypy-type-checker.args": [
"--config-file",
"${workspaceFolder}/pyproject.toml"
],
"mypy-type-checker.path": [
"${workspaceFolder}"
]
}
```
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"paths": {
"@/.source": ["./.source/index.ts"],
"@/*": ["./src/*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"]
}
```
--------------------------------------------------------------------------------
/libs/xfce/src/supervisor/supervisord.conf:
--------------------------------------------------------------------------------
```
[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisor
[program:vncserver]
command=/usr/local/bin/start-vnc.sh
user=cua
autorestart=true
stdout_logfile=/var/log/supervisor/vncserver.log
stderr_logfile=/var/log/supervisor/vncserver.error.log
priority=10
[program:novnc]
command=/usr/local/bin/start-novnc.sh
user=cua
autorestart=true
stdout_logfile=/var/log/supervisor/novnc.log
stderr_logfile=/var/log/supervisor/novnc.error.log
priority=20
[program:computer-server]
command=/usr/local/bin/start-computer-server.sh
user=cua
autorestart=true
stdout_logfile=/var/log/supervisor/computer-server.log
stderr_logfile=/var/log/supervisor/computer-server.error.log
priority=30
```
--------------------------------------------------------------------------------
/docs/src/mdx-components.tsx:
--------------------------------------------------------------------------------
```typescript
import defaultMdxComponents from 'fumadocs-ui/mdx';
import * as TabsComponents from 'fumadocs-ui/components/tabs';
import type { MDXComponents } from 'mdx/types';
import { Mermaid } from './components/mermaid';
import IOU from './components/iou';
import {
EditableCodeBlock,
EditableValue,
EditableForm,
EditableInput,
} from './components/editable-code-block';
import { Hero } from './components/hero';
// use this function to get MDX components, you will need it for rendering MDX
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
Mermaid,
IOU,
EditableCodeBlock,
EditableValue,
EditableForm,
EditableInput,
Hero,
...TabsComponents,
...components,
};
}
```
--------------------------------------------------------------------------------
/libs/qemu-docker/linux/src/vm/setup/setup.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Main Setup Script for Linux
# Installs dependencies and sets up CUA Computer Server
set -e
SCRIPT_DIR="/opt/oem"
LOG_FILE="$SCRIPT_DIR/setup.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== Running Main Setup ==="
# Update package lists
log "Updating package lists..."
sudo apt-get update
# Install Git
log "Installing Git..."
sudo apt-get install -y git
# Setup CUA Computer Server
log "Setting up CUA Computer Server..."
if [ -f "$SCRIPT_DIR/setup-cua-server.sh" ]; then
bash "$SCRIPT_DIR/setup-cua-server.sh" 2>&1 | tee -a "$LOG_FILE"
log "CUA Computer Server setup completed."
else
log "ERROR: setup-cua-server.sh not found at $SCRIPT_DIR/setup-cua-server.sh"
fi
log "=== Main Setup Completed ==="
```
--------------------------------------------------------------------------------
/.github/workflows/docker-publish-cua-linux.yml:
--------------------------------------------------------------------------------
```yaml
name: Build and Publish CUA Linux Container
on:
push:
branches:
- main
tags:
- "docker-cua-linux-v*.*.*"
paths:
- "libs/qemu-docker/linux/**"
- ".github/workflows/docker-publish-cua-linux.yml"
- ".github/workflows/docker-reusable-publish.yml"
pull_request:
paths:
- "libs/qemu-docker/linux/**"
- ".github/workflows/docker-publish-cua-linux.yml"
- ".github/workflows/docker-reusable-publish.yml"
jobs:
publish:
uses: ./.github/workflows/docker-reusable-publish.yml
with:
image_name: cua-linux
context_dir: libs/qemu-docker/linux
dockerfile_path: Dockerfile
tag_prefix: docker-cua-linux-v
docker_hub_org: trycua
secrets:
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
```
--------------------------------------------------------------------------------
/.github/workflows/docker-publish-cua-windows.yml:
--------------------------------------------------------------------------------
```yaml
name: Build and Publish CUA Windows Container
on:
push:
branches:
- main
tags:
- "docker-cua-windows-v*.*.*"
paths:
- "libs/qemu-docker/windows/**"
- ".github/workflows/docker-publish-cua-windows.yml"
- ".github/workflows/docker-reusable-publish.yml"
pull_request:
paths:
- "libs/qemu-docker/windows/**"
- ".github/workflows/docker-publish-cua-windows.yml"
- ".github/workflows/docker-reusable-publish.yml"
jobs:
publish:
uses: ./.github/workflows/docker-reusable-publish.yml
with:
image_name: cua-windows
context_dir: libs/qemu-docker/windows
dockerfile_path: Dockerfile
tag_prefix: docker-cua-windows-v
docker_hub_org: trycua
secrets:
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
```
--------------------------------------------------------------------------------
/libs/lume/src/VM/VMDisplayResolution.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
import ArgumentParser
struct VMDisplayResolution: Codable, ExpressibleByArgument {
let width: Int
let height: Int
init?(string: String) {
let components = string.components(separatedBy: "x")
guard components.count == 2,
let width = Int(components[0]),
let height = Int(components[1]),
width > 0, height > 0 else {
return nil
}
self.width = width
self.height = height
}
var string: String {
"\(width)x\(height)"
}
init?(argument: String) {
guard let resolution = VMDisplayResolution(string: argument) else { return nil }
self = resolution
}
}
```
--------------------------------------------------------------------------------
/libs/python/computer/computer/interface/macos.py:
--------------------------------------------------------------------------------
```python
from typing import Optional
from .generic import GenericComputerInterface
class MacOSComputerInterface(GenericComputerInterface):
"""Interface for macOS."""
def __init__(
self,
ip_address: str,
username: str = "lume",
password: str = "lume",
api_key: Optional[str] = None,
vm_name: Optional[str] = None,
api_port: Optional[int] = None,
):
super().__init__(
ip_address, username, password, api_key, vm_name, "computer.interface.macos", api_port
)
async def diorama_cmd(self, action: str, arguments: Optional[dict] = None) -> dict:
"""Send a diorama command to the server (macOS only)."""
return await self._send_command(
"diorama_cmd", {"action": action, "arguments": arguments or {}}
)
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Get.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Get: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Get detailed information about a virtual machine"
)
@Argument(help: "Name of the virtual machine", completion: .custom(completeVMName))
var name: String
@Option(name: [.long, .customShort("f")], help: "Output format (json|text)")
var format: FormatOption = .text
@Option(name: .customLong("storage"), help: "VM storage location to use or direct path to VM location")
var storage: String?
init() {
}
@MainActor
func run() async throws {
let vmController = LumeController()
let vm = try vmController.get(name: name, storage: storage)
try VMDetailsPrinter.printStatus([vm.details], format: self.format)
}
}
```
--------------------------------------------------------------------------------
/libs/qemu-docker/windows/src/vm/setup/install.bat:
--------------------------------------------------------------------------------
```
@echo off
SET ScriptFolder=C:\OEM
SET LogFile=%ScriptFolder%\ps_script_log.txt
echo Running PowerShell script... > %LogFile%
:: Check for PowerShell availability
where powershell >> %LogFile% 2>&1
if %ERRORLEVEL% neq 0 (
echo PowerShell is not available! >> %LogFile%
echo PowerShell is not available!
exit /b 1
)
:: Add a 30-second delay
echo Waiting for 30 seconds before continuing... >> %LogFile%
timeout /t 30 /nobreak >> %LogFile% 2>&1
:: Run PowerShell script with ExecutionPolicy Bypass and log errors
echo Running setup.ps1... >> %LogFile%
powershell -ExecutionPolicy Bypass -File "%ScriptFolder%\setup.ps1" >> %LogFile% 2>&1
if %ERRORLEVEL% neq 0 (
echo An error occurred. See %LogFile% for details.
) else (
echo PowerShell script has completed successfully.
)
echo PowerShell script has completed.
```
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
```yaml
# These are supported funding model platforms
github: trycua
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
```
--------------------------------------------------------------------------------
/docs/content/docs/computer-sdk/computer-server/index.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Computer Server
description: HTTP/WebSocket server for remote computer control
---
The Computer Server is an HTTP and WebSocket server that runs inside each Cua sandbox (VM or container). It exposes APIs for remote computer control - allowing the Computer SDK and agents to execute actions like clicking, typing, taking screenshots, and running commands on the sandboxed environment.
When you use `Computer(provider_type="cloud")` or any other provider, the Computer SDK communicates with this server running inside the sandbox to execute your automation commands.
## Key Features
- **REST API** - Execute commands, take screenshots, manage files
- **WebSocket API** - Real-time streaming for continuous interaction
- **Cross-platform** - Runs on Linux, macOS, and Windows sandboxes
- **Secure** - Isolated inside the sandbox environment
```
--------------------------------------------------------------------------------
/docs/src/app/sitemap.ts:
--------------------------------------------------------------------------------
```typescript
import { MetadataRoute } from 'next';
import { source } from '@/lib/source';
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://cua.ai';
// Get all pages from fumadocs source
const pages = source.getPages();
// Map pages to sitemap entries with /docs prefix
const docPages = pages.map((page) => {
// Ensure URL starts with /docs
const url = page.url.startsWith('/docs') ? page.url : `/docs${page.url}`;
return {
url: `${baseUrl}${url}`,
lastModified: new Date(),
changeFrequency: 'weekly' as const,
priority: url === '/docs' ? 1.0 : 0.8,
};
});
// Add main docs page if not included
const mainDocsPage = {
url: `${baseUrl}/docs`,
lastModified: new Date(),
changeFrequency: 'weekly' as const,
priority: 1.0,
};
return [mainDocsPage, ...docPages];
}
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/mcp-server/llm-integrations.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: LLM Integrations
---
## LiteLLM Integration
This MCP server features comprehensive liteLLM integration, allowing you to use any supported LLM provider with a simple model string configuration.
- **Unified Configuration**: Use a single `CUA_MODEL_NAME` environment variable with a model string
- **Automatic Provider Detection**: The agent automatically detects the provider and capabilities from the model string
- **Extensive Provider Support**: Works with Anthropic, OpenAI, local models, and any liteLLM-compatible provider
### Model String Examples:
- **Anthropic**: `"anthropic/claude-sonnet-4-5-20250929"`
- **OpenAI**: `"openai/computer-use-preview"`
- **UI-TARS**: `"huggingface-local/ByteDance-Seed/UI-TARS-1.5-7B"`
- **Omni + Any LiteLLM**: `"omniparser+litellm/gpt-4o"`, `"omniparser+litellm/claude-3-haiku"`, `"omniparser+ollama_chat/gemma3"`
```
--------------------------------------------------------------------------------
/examples/computer_ui_examples.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Simple example script for the Computer Interface Gradio UI.
This script launches the advanced Gradio UI for the Computer Interface
with full model selection and configuration options.
It can be run directly from the command line.
"""
from utils import load_dotenv_files
load_dotenv_files()
# Import the create_gradio_ui function
from computer.ui.gradio.app import create_gradio_ui
if __name__ == "__main__":
print("Launching Computer Interface Gradio UI with advanced features...")
app = create_gradio_ui()
app.launch(
share=False,
server_name="0.0.0.0",
server_port=7860,
)
# Optional: Using the saved dataset
# import datasets
# from computer.ui.utils import convert_to_unsloth
# ds = datasets.load_dataset("ddupont/highquality-cua-demonstrations")
# ds = convert_to_unsloth(ds)
```
--------------------------------------------------------------------------------
/libs/typescript/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "cua-ts",
"version": "1.0.0",
"description": "The Cua typescript libs.",
"keywords": [],
"author": "cua",
"license": "MIT",
"scripts": {
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"build:core": "pnpm --filter @trycua/core build",
"build:computer": "pnpm --filter @trycua/computer build",
"build": "pnpm build:core && pnpm build:computer",
"test:core": "pnpm --filter @trycua/core test",
"test:computer": "pnpm --filter @trycua/computer test",
"test": "pnpm -r test",
"typecheck": "pnpm -r typecheck",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"packageManager": "[email protected]",
"devDependencies": {
"prettier": "^3.6.2"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild",
"protobufjs",
"sharp",
"unrs-resolver"
]
}
}
```
--------------------------------------------------------------------------------
/libs/lume/src/Utils/Logger.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
struct Logger {
typealias Metadata = [String: String]
enum Level: String {
case info
case error
case debug
}
static func info(_ message: String, metadata: Metadata = [:]) {
log(.info, message, metadata)
}
static func error(_ message: String, metadata: Metadata = [:]) {
log(.error, message, metadata)
}
static func debug(_ message: String, metadata: Metadata = [:]) {
log(.debug, message, metadata)
}
private static func log(_ level: Level, _ message: String, _ metadata: Metadata) {
let timestamp = ISO8601DateFormatter().string(from: Date())
let metadataString = metadata.isEmpty ? "" : " " + metadata.map { "\($0.key)=\($0.value)" }.joined(separator: " ")
print("[\(timestamp)] \(level.rawValue.uppercased()): \(message)\(metadataString)")
}
}
```
--------------------------------------------------------------------------------
/.github/workflows/ci-lume.yml:
--------------------------------------------------------------------------------
```yaml
name: lume
on:
push:
branches:
- "main"
paths:
- "libs/lume/**"
- ".github/workflows/ci-lume.yml"
pull_request:
paths:
- "libs/lume/**"
- ".github/workflows/ci-lume.yml"
concurrency:
group: lume-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Runner images: https://github.com/actions/runner-images
jobs:
test:
name: Test
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- run: uname -a
- run: sudo xcode-select -s /Applications/Xcode_16.app # Swift 6.0
- run: swift test
working-directory: ./libs/lume
build:
name: Release build
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- run: uname -a
- run: sudo xcode-select -s /Applications/Xcode_16.app # Swift 6.0
- run: swift build --configuration release
working-directory: ./libs/lume
```
--------------------------------------------------------------------------------
/libs/typescript/computer/tests/interface/linux.test.ts:
--------------------------------------------------------------------------------
```typescript
import { describe, expect, it } from 'vitest';
import { LinuxComputerInterface } from '../../src/interface/linux.ts';
import { MacOSComputerInterface } from '../../src/interface/macos.ts';
describe('LinuxComputerInterface', () => {
const testParams = {
ipAddress: 'test.cua.com', // TEST-NET-1 address (RFC 5737) - guaranteed not to be routable
username: 'testuser',
password: 'testpass',
apiKey: 'test-api-key',
vmName: 'test-vm',
};
describe('Inheritance', () => {
it('should extend MacOSComputerInterface', () => {
const linuxInterface = new LinuxComputerInterface(
testParams.ipAddress,
testParams.username,
testParams.password,
testParams.apiKey,
testParams.vmName
);
expect(linuxInterface).toBeInstanceOf(MacOSComputerInterface);
expect(linuxInterface).toBeInstanceOf(LinuxComputerInterface);
});
});
});
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Clone.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Clone: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Clone an existing virtual machine"
)
@Argument(help: "Name of the source virtual machine", completion: .custom(completeVMName))
var name: String
@Argument(help: "Name for the cloned virtual machine")
var newName: String
@Option(name: .customLong("source-storage"), help: "Source VM storage location")
var sourceStorage: String?
@Option(name: .customLong("dest-storage"), help: "Destination VM storage location")
var destStorage: String?
init() {}
@MainActor
func run() async throws {
let vmController = LumeController()
try vmController.clone(
name: name,
newName: newName,
sourceLocation: sourceStorage,
destLocation: destStorage
)
}
}
```
--------------------------------------------------------------------------------
/libs/typescript/computer/tests/interface/windows.test.ts:
--------------------------------------------------------------------------------
```typescript
import { describe, expect, it } from 'vitest';
import { MacOSComputerInterface } from '../../src/interface/macos.ts';
import { WindowsComputerInterface } from '../../src/interface/windows.ts';
describe('WindowsComputerInterface', () => {
const testParams = {
ipAddress: '192.0.2.1', // TEST-NET-1 address (RFC 5737) - guaranteed not to be routable
username: 'testuser',
password: 'testpass',
apiKey: 'test-api-key',
vmName: 'test-vm',
};
describe('Inheritance', () => {
it('should extend MacOSComputerInterface', () => {
const windowsInterface = new WindowsComputerInterface(
testParams.ipAddress,
testParams.username,
testParams.password,
testParams.apiKey,
testParams.vmName
);
expect(windowsInterface).toBeInstanceOf(MacOSComputerInterface);
expect(windowsInterface).toBeInstanceOf(WindowsComputerInterface);
});
});
});
```
--------------------------------------------------------------------------------
/libs/lume/src/VM/VMFactory.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
import Virtualization
enum VMType: String {
case darwin = "macOS"
case linux = "linux"
}
protocol VMFactory {
@MainActor
func createVM(
vmDirContext: VMDirContext,
imageLoader: ImageLoader?
) throws -> VM
}
class DefaultVMFactory: VMFactory {
@MainActor
func createVM(
vmDirContext: VMDirContext,
imageLoader: ImageLoader?
) throws -> VM {
let osType = vmDirContext.config.os.lowercased()
switch osType {
case "macos", "darwin":
guard let imageLoader = imageLoader else {
throw VMError.internalError("ImageLoader required for macOS VM")
}
return DarwinVM(vmDirContext: vmDirContext, imageLoader: imageLoader)
case "linux":
return LinuxVM(vmDirContext: vmDirContext)
default:
throw VMError.unsupportedOS(osType)
}
}
}
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/benchmarks/index.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Benchmarks
description: Computer Agent SDK benchmarks for agentic GUI tasks
---
The benchmark system evaluates models on GUI grounding tasks, specifically agent loop success rate and click prediction accuracy. It supports both:
- **Computer Agent SDK providers** (using model strings like `"huggingface-local/HelloKKMe/GTA1-7B"`)
- **Reference agent implementations** (custom model classes implementing the `ModelProtocol`)
## Available Benchmarks
- **[ScreenSpot-v2](./benchmarks/screenspot-v2)** - Standard resolution GUI grounding
- **[ScreenSpot-Pro](./benchmarks/screenspot-pro)** - High-resolution GUI grounding
- **[Interactive Testing](./benchmarks/interactive)** - Real-time testing and visualization
## Quick Start
```bash
# Clone the benchmark repository
git clone https://github.com/trycua/cua
cd libs/python/agent/benchmarks
# Install dependencies
pip install "cua-agent[all]"
# Run a benchmark
python ss-v2.py
```
```
--------------------------------------------------------------------------------
/libs/python/agent/benchmarks/models/base.py:
--------------------------------------------------------------------------------
```python
"""
Base protocol for benchmark models.
"""
from typing import Optional, Protocol, Tuple
from PIL import Image
class ModelProtocol(Protocol):
"""Protocol for benchmark models that can predict click coordinates."""
@property
def model_name(self) -> str:
"""Return the name of the model."""
...
async def load_model(self) -> None:
"""Load the model into memory."""
...
async def unload_model(self) -> None:
"""Unload the model from memory."""
...
async def predict_click(
self, image: Image.Image, instruction: str
) -> Optional[Tuple[int, int]]:
"""
Predict click coordinates for the given image and instruction.
Args:
image: PIL Image to analyze
instruction: Text instruction describing what to click
Returns:
Tuple of (x, y) coordinates or None if prediction fails
"""
...
```
--------------------------------------------------------------------------------
/libs/lume/src/Server/Responses.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
struct APIError: Codable {
let message: String
}
// Helper struct to encode mixed-type dictionaries
struct AnyEncodable: Encodable {
private let value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
try value.encode(to: encoder)
}
}
extension HTTPResponse {
static func json<T: Encodable>(_ value: T) throws -> HTTPResponse {
let data = try JSONEncoder().encode(value)
return HTTPResponse(
statusCode: .ok,
headers: ["Content-Type": "application/json"],
body: data
)
}
static func badRequest(message: String) -> HTTPResponse {
let error = APIError(message: message)
return try! HTTPResponse(
statusCode: .badRequest,
headers: ["Content-Type": "application/json"],
body: JSONEncoder().encode(error)
)
}
}
```
--------------------------------------------------------------------------------
/libs/typescript/cua-cli/src/storage.ts:
--------------------------------------------------------------------------------
```typescript
import { Database } from 'bun:sqlite';
import { getDbPath } from './config';
function getDb(): Database {
const db = new Database(getDbPath());
db.exec('PRAGMA journal_mode = WAL;');
db.exec(
'CREATE TABLE IF NOT EXISTS kv (k TEXT PRIMARY KEY, v TEXT NOT NULL);'
);
return db;
}
export function setApiKey(token: string) {
const db = getDb();
try {
const stmt = db.query(
"INSERT INTO kv (k, v) VALUES ('api_key', ?) ON CONFLICT(k) DO UPDATE SET v=excluded.v"
);
stmt.run(token);
} finally {
db.close();
}
}
export function getApiKey(): string | null {
const db = getDb();
try {
const row = db.query("SELECT v FROM kv WHERE k='api_key'").get() as
| { v: string }
| undefined;
return row?.v ?? null;
} finally {
db.close();
}
}
export function clearApiKey() {
const db = getDb();
try {
db.query("DELETE FROM kv WHERE k='api_key'").run();
} finally {
db.close();
}
}
```
--------------------------------------------------------------------------------
/libs/python/bench-ui/examples/gui/logo.svg:
--------------------------------------------------------------------------------
```
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background circle -->
<circle cx="100" cy="100" r="95" fill="url(#grad1)" />
<!-- Window icon -->
<rect x="50" y="50" width="100" height="100" rx="8" fill="white" opacity="0.9" />
<!-- Window panes -->
<line x1="100" y1="50" x2="100" y2="150" stroke="url(#grad1)" stroke-width="4" />
<line x1="50" y1="100" x2="150" y2="100" stroke="url(#grad1)" stroke-width="4" />
<!-- Decorative dots -->
<circle cx="75" cy="75" r="8" fill="url(#grad1)" />
<circle cx="125" cy="75" r="8" fill="url(#grad1)" />
<circle cx="75" cy="125" r="8" fill="url(#grad1)" />
<circle cx="125" cy="125" r="8" fill="url(#grad1)" />
</svg>
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/List.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct List: AsyncParsableCommand {
static let configuration: CommandConfiguration = CommandConfiguration(
commandName: "ls",
abstract: "List virtual machines"
)
@Option(name: [.long, .customShort("f")], help: "Output format (json|text)")
var format: FormatOption = .text
@Option(name: .long, help: "Filter by storage location name")
var storage: String?
init() {
}
@MainActor
func run() async throws {
let manager = LumeController()
let vms = try manager.list(storage: self.storage)
if vms.isEmpty && self.format == .text {
if let storageName = self.storage {
print("No virtual machines found in storage '\(storageName)'")
} else {
print("No virtual machines found")
}
} else {
try VMDetailsPrinter.printStatus(vms, format: self.format)
}
}
}
```
--------------------------------------------------------------------------------
/libs/python/computer/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
name = "cua-computer"
version = "0.4.18"
description = "Computer-Use Interface (CUI) framework powering Cua"
readme = "README.md"
authors = [
{ name = "TryCua", email = "[email protected]" }
]
dependencies = [
"pillow>=10.0.0",
"websocket-client>=1.8.0",
"websockets>=12.0",
"aiohttp>=3.9.0",
"cua-core>=0.1.0,<0.2.0",
"pydantic>=2.11.1",
"mslex>=1.3.0",
]
requires-python = ">=3.12,<3.14"
[project.optional-dependencies]
lume = [
]
lumier = [
]
ui = [
"gradio>=5.23.3",
"python-dotenv>=1.0.1",
"datasets>=3.6.0",
]
all = [
# Include all optional dependencies
"gradio>=5.23.3",
"python-dotenv>=1.0.1",
"datasets>=3.6.0",
]
[tool.pdm]
distribution = true
[tool.pdm.build]
includes = ["computer/"]
source-includes = ["tests/", "README.md", "LICENSE"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = "test_*.py"
```
--------------------------------------------------------------------------------
/docs/content/docs/macos-vm-cli-playbook/lumier/docker-compose.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Docker Compose
---
You can also use Docker Compose to run Lumier with a simple configuration file. Create a `docker-compose.yml` file with the following content:
```yaml
version: '3'
services:
lumier:
image: trycua/lumier:latest
container_name: lumier-vm
restart: unless-stopped
ports:
- '8006:8006' # Port for VNC access
volumes:
- ./storage:/storage # VM persistent storage
- ./shared:/shared # Shared folder accessible in the VM
environment:
- VM_NAME=lumier-vm
- VERSION=ghcr.io/trycua/macos-sequoia-cua:latest
- CPU_CORES=4
- RAM_SIZE=8192
- HOST_STORAGE_PATH=${PWD}/storage
- HOST_SHARED_PATH=${PWD}/shared
stop_signal: SIGINT
stop_grace_period: 2m
```
Then run Lumier using:
```bash
# First create the required directories
mkdir -p storage shared
# Start the container
docker-compose up -d
# View the logs
docker-compose logs -f
# Stop the container when done
docker-compose down
```
```
--------------------------------------------------------------------------------
/libs/lume/tests/Mocks/MockVNCService.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
@testable import lume
@MainActor
final class MockVNCService: VNCService {
private(set) var url: String?
private(set) var isRunning = false
private(set) var clientOpenCount = 0
private var _attachedVM: Any?
private let vmDirectory: VMDirectory
init(vmDirectory: VMDirectory) {
self.vmDirectory = vmDirectory
}
nonisolated var attachedVM: String? {
get async {
await Task { @MainActor in
_attachedVM as? String
}.value
}
}
func start(port: Int, virtualMachine: Any?) async throws {
isRunning = true
url = "vnc://localhost:\(port)"
_attachedVM = virtualMachine
}
func stop() {
isRunning = false
url = nil
_attachedVM = nil
}
func openClient(url: String) async throws {
guard isRunning else {
throw VMError.vncNotConfigured
}
clientOpenCount += 1
}
}
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/supported-model-providers/local-models.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Running Models Locally
---
You can run open-source LLMs and vision models on your own machine using Cua, without relying on cloud APIs. This is ideal for development, privacy, or running on air-gapped systems.
## Hugging Face (transformers)
Use the `huggingface-local/` prefix to run any Hugging Face model locally via the `transformers` library. This supports most text and vision models from the Hugging Face Hub.
**Example:**
```python
model = "huggingface-local/ByteDance-Seed/UI-TARS-1.5-7B"
```
## MLX (Apple Silicon)
Use the `mlx/` prefix to run models using the `mlx-vlm` library, optimized for Apple Silicon (M1/M2/M3). This allows fast, local inference for many open-source models.
**Example:**
```python
model = "mlx/mlx-community/UI-TARS-1.5-7B-6bit"
```
## Ollama
Use the `ollama_chat/` prefix to run models using the `ollama` library. This allows fast, local inference for many open-source models.
**Example:**
```python
model = "omniparser+ollama_chat/llama3.2:latest"
```
```
--------------------------------------------------------------------------------
/docs/src/lib/llms.ts:
--------------------------------------------------------------------------------
```typescript
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import remarkMdx from 'remark-mdx';
import { remarkInclude } from 'fumadocs-mdx/config';
import { source } from '@/lib/source';
import type { InferPageType } from 'fumadocs-core/source';
const processor = remark()
.use(remarkMdx)
// needed for Fumadocs MDX
.use(remarkInclude)
.use(remarkGfm);
export async function getLLMText(page: InferPageType<typeof source>) {
const pageData = page.data as any;
const filePath = pageData._file?.absolutePath;
const content = pageData.content || pageData.body || '';
let processed;
if (filePath && typeof content === 'string') {
processed = await processor.process({ path: filePath, value: content });
} else if (typeof content === 'string') {
processed = await processor.process(content);
} else {
// Handle case where content is not available
processed = { value: '' };
}
return `# ${page.data.title}
URL: ${page.url}
${page.data.description || ''}
${processed.value}`;
}
```
--------------------------------------------------------------------------------
/libs/typescript/cua-cli/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "@trycua/cli",
"version": "0.1.7",
"packageManager": "[email protected]",
"description": "Command-line interface for CUA cloud sandboxes and authentication",
"type": "module",
"license": "MIT",
"homepage": "https://github.com/trycua/cua/tree/main/libs/typescript/cua-cli",
"bugs": {
"url": "https://github.com/trycua/cua/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/trycua/cua.git"
},
"author": "cua",
"files": [
"index.ts",
"src",
"README.md"
],
"bin": {
"cua": "./index.ts"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"typecheck": "tsc --noEmit",
"release": "bumpp && bun publish",
"prepublishOnly": "bun run typecheck"
},
"dependencies": {
"yargs": "^18.0.0"
},
"devDependencies": {
"@types/bun": "latest",
"@types/yargs": "^17.0.33",
"bumpp": "^10.1.0",
"prettier": "^3.0.0",
"typescript": "^5"
}
}
```
--------------------------------------------------------------------------------
/libs/lume/src/Main.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
@main
struct Lume: AsyncParsableCommand {
static var configuration: CommandConfiguration {
CommandConfiguration(
commandName: "lume",
abstract: "A lightweight CLI and local API server to build, run and manage macOS VMs.",
version: Version.current,
subcommands: CommandRegistry.allCommands,
helpNames: .long
)
}
}
// MARK: - Version Management
extension Lume {
enum Version {
static let current: String = "0.1.0"
}
}
// MARK: - Command Execution
extension Lume {
public static func main() async {
do {
try await executeCommand()
} catch {
exit(withError: error)
}
}
private static func executeCommand() async throws {
var command = try parseAsRoot()
if var asyncCommand = command as? AsyncParsableCommand {
try await asyncCommand.run()
} else {
try command.run()
}
}
}
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/human_tool/__main__.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Human-in-the-Loop Completion Server and UI
This module combines the FastAPI server for handling completion requests
with a Gradio UI for human interaction.
"""
import gradio as gr
from fastapi import FastAPI
from .server import app as fastapi_app
from .ui import create_ui
# Create the Gradio demo
gradio_demo = create_ui()
# Mount Gradio on FastAPI
CUSTOM_PATH = "/gradio"
app = gr.mount_gradio_app(fastapi_app, gradio_demo, path=CUSTOM_PATH)
# Add a redirect from root to Gradio UI
@fastapi_app.get("/")
async def redirect_to_ui():
"""Redirect root to Gradio UI."""
return {
"message": "Human Completion Server is running",
"ui_url": "/gradio",
"api_docs": "/docs",
}
if __name__ == "__main__":
import uvicorn
print("🚀 Starting Human-in-the-Loop Completion Server...")
print("📊 API Server: http://localhost:8002")
print("🎨 Gradio UI: http://localhost:8002/gradio")
print("📚 API Docs: http://localhost:8002/docs")
uvicorn.run(app, host="0.0.0.0", port=8002)
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/types.py:
--------------------------------------------------------------------------------
```python
"""
Type definitions for agent
"""
import re
from collections.abc import Iterable
from typing import Any, Callable, Dict, List, Literal, Optional, Protocol
from litellm import ResponseInputParam, ResponsesAPIResponse, ToolParam
from pydantic import BaseModel
# Agent input types
Messages = str | ResponseInputParam | List[Dict[str, Any]]
Tools = Optional[Iterable[ToolParam]]
# Agent output types
AgentResponse = ResponsesAPIResponse
AgentCapability = Literal["step", "click"]
# Exception types
class ToolError(RuntimeError):
"""Base exception for tool-related errors"""
pass
class IllegalArgumentError(ToolError):
"""Exception raised when function arguments are invalid"""
pass
# Agent config registration
class AgentConfigInfo(BaseModel):
"""Information about a registered agent config"""
agent_class: type
models_regex: str
priority: int = 0
def matches_model(self, model: str) -> bool:
"""Check if this agent config matches the given model"""
return bool(re.match(self.models_regex, model))
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/custom-tools.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Custom Tools
slug: custom-tools
---
The Agent SDK supports defining custom Python tools that run securely in sandboxed environments on remote Cua Computers. This enables safe execution of user-defined functions, isolation of dependencies, and robust automation workflows.
## Custom Tools
Define a custom tool for an agent:
```python
def calculate(a: int, b: int) -> int:
"""Calculate the sum of two integers"""
return a + b
# Use with agent
agent = ComputerAgent(
model="cua/anthropic/claude-sonnet-4.5",
tools=[computer, calculate]
)
```
## Sandboxed Tools
Define a sandboxed tool:
```python
from computer.helpers import sandboxed
@sandboxed()
def read_file(location: str) -> str:
"""Read contents of a file"""
with open(location, 'r') as f:
return f.read()
```
You can then register this as a tool for your agent:
```python
from agent import ComputerAgent
from computer import Computer
computer = Computer(...)
agent = ComputerAgent(
model="cua/anthropic/claude-sonnet-4.5",
tools=[computer, read_file],
)
```
```
--------------------------------------------------------------------------------
/libs/xfce/src/xfce-config/xfce4-power-manager.xml:
--------------------------------------------------------------------------------
```
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-power-manager" version="1.0">
<property name="xfce4-power-manager" type="empty">
<property name="dpms-enabled" type="bool" value="false"/>
<property name="dpms-on-ac-sleep" type="uint" value="0"/>
<property name="dpms-on-ac-off" type="uint" value="0"/>
<property name="dpms-on-battery-sleep" type="uint" value="0"/>
<property name="dpms-on-battery-off" type="uint" value="0"/>
<property name="blank-on-ac" type="int" value="0"/>
<property name="blank-on-battery" type="int" value="0"/>
<property name="lock-screen-suspend-hibernate" type="bool" value="false"/>
<property name="logind-handle-lid-switch" type="bool" value="false"/>
<property name="brightness-on-ac" type="uint" value="9"/>
<property name="brightness-on-battery" type="uint" value="9"/>
<property name="inactivity-on-ac" type="uint" value="0"/>
<property name="inactivity-on-battery" type="uint" value="0"/>
<property name="inactivity-sleep-mode-on-battery" type="uint" value="1"/>
</property>
</channel>
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Delete.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Delete: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Delete a virtual machine"
)
@Argument(help: "Name of the virtual machine to delete", completion: .custom(completeVMName))
var name: String
@Flag(name: .long, help: "Force deletion without confirmation")
var force = false
@Option(name: .customLong("storage"), help: "VM storage location to use or direct path to VM location")
var storage: String?
init() {}
@MainActor
func run() async throws {
if !force {
print(
"Are you sure you want to delete the virtual machine '\(name)'? [y/N] ",
terminator: "")
guard let response = readLine()?.lowercased(),
response == "y" || response == "yes"
else {
print("Deletion cancelled")
return
}
}
let vmController = LumeController()
try await vmController.delete(name: name, storage: storage)
}
}
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Pull.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Pull: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Pull a macOS image from GitHub Container Registry"
)
@Argument(help: "Image to pull (format: name:tag)")
var image: String
@Argument(
help: "Name for the VM (defaults to image name without tag)", transform: { Optional($0) })
var name: String?
@Option(help: "Github Container Registry to pull from. Defaults to ghcr.io")
var registry: String = "ghcr.io"
@Option(help: "Organization to pull from. Defaults to trycua")
var organization: String = "trycua"
@Option(name: .customLong("storage"), help: "VM storage location to use or direct path to VM location")
var storage: String?
init() {}
@MainActor
func run() async throws {
let controller = LumeController()
try await controller.pullImage(
image: image,
name: name,
registry: registry,
organization: organization,
storage: storage
)
}
}
```
--------------------------------------------------------------------------------
/docs/src/app/global.css:
--------------------------------------------------------------------------------
```css
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* Custom Sky + Emerald theme */
@theme {
--color-fd-primary: hsl(199, 89%, 48%); /* sky-500 */
--color-fd-primary-foreground: hsl(0, 0%, 100%);
--color-fd-ring: hsl(199, 89%, 48%); /* sky-500 */
--color-fd-muted: hsl(160, 84%, 95%); /* emerald-50 */
--color-fd-accent: hsl(152, 76%, 92%); /* emerald-100 */
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
.dark {
--color-fd-primary: hsl(199, 89%, 48%); /* sky-500 */
--color-fd-primary-foreground: hsl(0, 0%, 100%);
--color-fd-ring: hsl(199, 89%, 48%); /* sky-500 */
--color-fd-muted: hsl(199, 89%, 14%); /* sky-950 */
--color-fd-accent: hsl(199, 89%, 20%); /* sky dark */
}
.dark body {
background-image: linear-gradient(
rgba(14, 165, 233, 0.1),
transparent 20rem,
transparent
);
background-repeat: no-repeat;
}
/* Fix TOC overflow on production builds */
#nd-toc {
overflow-y: auto;
overflow-x: hidden;
}
#nd-toc > div {
overflow-y: auto;
overflow-x: hidden;
}
```
--------------------------------------------------------------------------------
/libs/python/computer/computer/providers/types.py:
--------------------------------------------------------------------------------
```python
"""Shared provider type definitions for VM metadata and responses.
These base types describe the common shape of objects returned by provider
methods like `list_vms()`.
"""
from __future__ import annotations
from typing import Literal, NotRequired, TypedDict
# Core status values per product docs
VMStatus = Literal[
"pending", # VM deployment in progress
"running", # VM is active and accessible
"stopped", # VM is stopped but not terminated
"terminated", # VM has been permanently destroyed
"failed", # VM deployment or operation failed
]
OSType = Literal["macos", "linux", "windows"]
class MinimalVM(TypedDict):
"""Minimal VM object shape returned by list calls.
Providers may include additional fields. Optional fields below are
common extensions some providers expose or that callers may compute.
"""
name: str
status: VMStatus
# Not always included by all providers
password: NotRequired[str]
vnc_url: NotRequired[str]
api_url: NotRequired[str]
# Convenience alias for list_vms() responses
ListVMsResponse = list[MinimalVM]
```
--------------------------------------------------------------------------------
/libs/python/bench-ui/examples/folder_example.py:
--------------------------------------------------------------------------------
```python
from __future__ import annotations
import time
from bench_ui import launch_window, get_element_rect, execute_javascript
from pathlib import Path
import os
def main():
os.environ["CUA_BENCH_UI_DEBUG"] = "1"
# Get the path to the gui folder
gui_folder = Path(__file__).parent / "gui"
# Launch a window serving the static folder
pid = launch_window(
folder=str(gui_folder),
title="Static Folder Example",
width=800,
height=600,
)
print(f"Launched window with PID: {pid}")
print(f"Serving folder: {gui_folder}")
# Give the window a moment to render
time.sleep(1.5)
# Query the client rect of the button element
rect = get_element_rect(pid, "#testButton", space="window")
print("Button rect (window space):", rect)
# Check if button has been clicked
clicked = execute_javascript(pid, "document.getElementById('testButton').disabled")
print("Button clicked:", clicked)
# Get the page title
title = execute_javascript(pid, "document.title")
print("Page title:", title)
if __name__ == "__main__":
main()
```
--------------------------------------------------------------------------------
/libs/lume/src/Utils/Path.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Path: CustomStringConvertible, ExpressibleByArgument {
let url: URL
init(_ path: String) {
url = URL(filePath: NSString(string: path).expandingTildeInPath).standardizedFileURL
}
init(_ url: URL) {
self.url = url
}
init(argument: String) {
self.init(argument)
}
func file(_ path: String) -> Path {
return Path(url.appendingPathComponent(path, isDirectory: false))
}
func directory(_ path: String) -> Path {
return Path(url.appendingPathComponent(path, isDirectory: true))
}
func exists() -> Bool {
return FileManager.default.fileExists(atPath: url.standardizedFileURL.path(percentEncoded: false))
}
func writable() -> Bool {
return FileManager.default.isWritableFile(atPath: url.standardizedFileURL.path(percentEncoded: false))
}
var name: String {
return url.lastPathComponent
}
var path: String {
return url.standardizedFileURL.path(percentEncoded: false)
}
var description: String {
return url.path()
}
}
```
--------------------------------------------------------------------------------
/libs/typescript/agent/tests/client.test.ts:
--------------------------------------------------------------------------------
```typescript
import { describe, it, expect } from 'vitest';
import AgentClient from '../src/index.js';
describe('AgentClient', () => {
it('should create client with HTTP URL', () => {
const client = new AgentClient('https://localhost:8000');
expect(client).toBeDefined();
expect(client.responses).toBeDefined();
expect(typeof client.responses.create).toBe('function');
});
it('should create client with peer URL', () => {
const client = new AgentClient('peer://test-peer-id');
expect(client).toBeDefined();
expect(client.responses).toBeDefined();
expect(typeof client.responses.create).toBe('function');
});
it('should throw error for invalid URL', () => {
expect(() => {
new AgentClient('invalid://url');
}).toThrow('Invalid URL format');
});
it('should have health method', async () => {
const client = new AgentClient('https://localhost:8000');
expect(typeof client.health).toBe('function');
});
it('should have disconnect method', async () => {
const client = new AgentClient('https://localhost:8000');
expect(typeof client.disconnect).toBe('function');
});
});
```
--------------------------------------------------------------------------------
/examples/docker_examples.py:
--------------------------------------------------------------------------------
```python
import asyncio
import os
from computer import Computer, VMProviderType
from computer.providers.factory import VMProviderFactory
async def main():
# # Create docker provider
# provider = VMProviderFactory.create_provider(
# provider_type="docker",
# image="cua-ubuntu:latest", # Your CUA Ubuntu image
# port=8080,
# vnc_port=6901
# )
# # Run a container
# async with provider:
# vm_info = await provider.run_vm(
# image="cua-ubuntu:latest",
# name="my-cua-container",
# run_opts={
# "memory": "4GB",
# "cpu": 2,
# "vnc_port": 6901,
# "api_port": 8080
# }
# )
# print(vm_info)
computer = Computer(
os_type="linux",
provider_type=VMProviderType.DOCKER,
name="my-cua-container",
image="cua-ubuntu:latest",
)
await computer.run()
screenshot = await computer.interface.screenshot()
with open("screenshot_docker.png", "wb") as f:
f.write(screenshot)
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------------------------------------------------------
/libs/python/computer/computer/__init__.py:
--------------------------------------------------------------------------------
```python
"""CUA Computer Interface for cross-platform computer control."""
import logging
import sys
__version__ = "0.1.0"
# Initialize logging
logger = logging.getLogger("computer")
# Initialize telemetry when the package is imported
try:
# Import from core telemetry
from core.telemetry import (
is_telemetry_enabled,
record_event,
)
# Check if telemetry is enabled
if is_telemetry_enabled():
logger.info("Telemetry is enabled")
# Record package initialization
record_event(
"module_init",
{
"module": "computer",
"version": __version__,
"python_version": sys.version,
},
)
else:
logger.info("Telemetry is disabled")
except ImportError as e:
# Telemetry not available
logger.warning(f"Telemetry not available: {e}")
except Exception as e:
# Other issues with telemetry
logger.warning(f"Error initializing telemetry: {e}")
# Core components
from .computer import Computer
# Provider components
from .providers.base import VMProviderType
__all__ = ["Computer", "VMProviderType"]
```
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev --turbo -p 8090",
"start": "next start -p 8090",
"postinstall": "fumadocs-mdx"
},
"dependencies": {
"fumadocs-core": "16.0.8",
"fumadocs-mdx": "13.0.8",
"fumadocs-ui": "16.0.8",
"lucide-react": "^0.525.0",
"mermaid": "^11.12.1",
"next": "16.0.7",
"next-themes": "^0.4.6",
"posthog-js": "^1.276.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-icons": "^5.5.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.1",
"remark-mdx": "^3.1.0",
"tailwind-merge": "^3.3.1",
"zod": "^4.1.12"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.8",
"@types/mdx": "^2.0.13",
"@types/node": "22.15.28",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"postcss": "^8.5.4",
"prettier": "^3.6.2",
"tailwindcss": "^4.1.8",
"typescript": "^5.8.3"
},
"pnpm": {
"onlyBuiltDependencies": [
"@tailwindcss/oxide",
"esbuild",
"sharp"
],
"overrides": {
"js-yaml@>=4.0.0 <4.1.1": ">=4.1.1"
}
}
}
```
--------------------------------------------------------------------------------
/libs/python/pylume/tests/test_pylume.py:
--------------------------------------------------------------------------------
```python
"""Unit tests for pylume package.
This file tests ONLY basic pylume functionality.
Following SRP: This file tests pylume module imports and basic operations.
All external dependencies are mocked.
"""
import pytest
class TestPylumeImports:
"""Test pylume module imports (SRP: Only tests imports)."""
def test_pylume_module_exists(self):
"""Test that pylume module can be imported."""
try:
import pylume
assert pylume is not None
except ImportError:
pytest.skip("pylume module not installed")
class TestPylumeInitialization:
"""Test pylume initialization (SRP: Only tests initialization)."""
def test_pylume_can_be_imported(self):
"""Basic smoke test: verify pylume components can be imported."""
try:
import pylume
# Check for basic attributes
assert pylume is not None
except ImportError:
pytest.skip("pylume module not available")
except Exception as e:
# Some initialization errors are acceptable in unit tests
pytest.skip(f"pylume initialization requires specific setup: {e}")
```
--------------------------------------------------------------------------------
/libs/python/computer/computer/models.py:
--------------------------------------------------------------------------------
```python
"""Models for computer configuration."""
from dataclasses import dataclass
from typing import Any, Dict, Optional
# Import base provider interface
from .providers.base import BaseVMProvider
@dataclass
class Display:
"""Display configuration."""
width: int
height: int
@dataclass
class Image:
"""VM image configuration."""
image: str
tag: str
name: str
@dataclass
class Computer:
"""Computer configuration."""
image: str
tag: str
name: str
display: Display
memory: str
cpu: str
vm_provider: Optional[BaseVMProvider] = None
# @property # Remove the property decorator
async def get_ip(self) -> Optional[str]:
"""Get the IP address of the VM."""
if not self.vm_provider:
return None
vm = await self.vm_provider.get_vm(self.name)
# Handle both object attribute and dictionary access for ip_address
if vm:
if isinstance(vm, dict):
return vm.get("ip_address")
else:
# Access as attribute for object-based return values
return getattr(vm, "ip_address", None)
return None
```
--------------------------------------------------------------------------------
/libs/python/core/tests/conftest.py:
--------------------------------------------------------------------------------
```python
"""Pytest configuration and shared fixtures for core package tests.
This file contains shared fixtures and configuration for all core tests.
Following SRP: This file ONLY handles test setup/teardown.
"""
from unittest.mock import AsyncMock, Mock, patch
import pytest
@pytest.fixture
def mock_httpx_client():
"""Mock httpx.AsyncClient for API calls.
Use this fixture to avoid making real HTTP requests during tests.
"""
with patch("httpx.AsyncClient") as mock_client:
mock_instance = AsyncMock()
mock_client.return_value.__aenter__.return_value = mock_instance
yield mock_instance
@pytest.fixture
def mock_posthog():
"""Mock PostHog client for telemetry tests.
Use this fixture to avoid sending real telemetry during tests.
"""
with patch("posthog.Posthog") as mock_ph:
mock_instance = Mock()
mock_ph.return_value = mock_instance
yield mock_instance
@pytest.fixture
def disable_telemetry(monkeypatch):
"""Disable telemetry for tests that don't need it.
Use this fixture to ensure telemetry is disabled during tests.
"""
monkeypatch.setenv("CUA_TELEMETRY_DISABLED", "1")
yield
```
--------------------------------------------------------------------------------
/docs/src/assets/discord-black.svg:
--------------------------------------------------------------------------------
```
<?xml version="1.0" encoding="UTF-8"?><svg id="Discord-Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126.644 96"><path fill="currentColor" id="Discord-Symbol-Black" d="M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z"/></svg>
```
--------------------------------------------------------------------------------
/libs/lume/tests/Mocks/MockVM.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
@testable import lume
@MainActor
class MockVM: VM {
private var mockIsRunning = false
override func getOSType() -> String {
return "mock-os"
}
override func setup(
ipswPath: String, cpuCount: Int, memorySize: UInt64, diskSize: UInt64, display: String
) async throws {
// Mock setup implementation
vmDirContext.config.setCpuCount(cpuCount)
vmDirContext.config.setMemorySize(memorySize)
vmDirContext.config.setDiskSize(diskSize)
vmDirContext.config.setMacAddress("00:11:22:33:44:55")
try vmDirContext.saveConfig()
}
override func run(
noDisplay: Bool, sharedDirectories: [SharedDirectory], mount: Path?, vncPort: Int = 0,
recoveryMode: Bool = false, usbMassStoragePaths: [Path]? = nil
) async throws {
mockIsRunning = true
try await super.run(
noDisplay: noDisplay, sharedDirectories: sharedDirectories, mount: mount,
vncPort: vncPort, recoveryMode: recoveryMode,
usbMassStoragePaths: usbMassStoragePaths
)
}
override func stop() async throws {
mockIsRunning = false
try await super.stop()
}
}
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Set.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Set: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Set new values for CPU, memory, and disk size of a virtual machine"
)
@Argument(help: "Name of the virtual machine", completion: .custom(completeVMName))
var name: String
@Option(help: "New number of CPU cores")
var cpu: Int?
@Option(help: "New memory size, e.g., 8192MB or 8GB.", transform: { try parseSize($0) })
var memory: UInt64?
@Option(help: "New disk size, e.g., 20480MB or 20GB.", transform: { try parseSize($0) })
var diskSize: UInt64?
@Option(help: "New display resolution in format WIDTHxHEIGHT.")
var display: VMDisplayResolution?
@Option(name: .customLong("storage"), help: "VM storage location to use or direct path to VM location")
var storage: String?
init() {
}
@MainActor
func run() async throws {
let vmController = LumeController()
try vmController.updateSettings(
name: name,
cpu: cpu,
memory: memory,
diskSize: diskSize,
display: display?.string,
storage: storage
)
}
}
```
--------------------------------------------------------------------------------
/libs/python/bench-ui/examples/gui/index.html:
--------------------------------------------------------------------------------
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Static Folder Example</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Static Folder Example</h1>
<p>This page is served from a static folder using bench-ui!</p>
<div class="image-container">
<img src="logo.svg" alt="Example SVG Logo" class="logo">
</div>
<div class="info">
<p>This example demonstrates:</p>
<ul>
<li>Serving a static folder with bench-ui</li>
<li>Loading external CSS files (styles.css)</li>
<li>Loading SVG images (logo.svg)</li>
</ul>
</div>
<button id="testButton" class="btn">Click Me!</button>
<p id="status"></p>
</div>
<script>
document.getElementById('testButton').addEventListener('click', function () {
document.getElementById('status').textContent = 'Button clicked! ✓';
this.disabled = true;
this.textContent = 'Clicked!';
});
</script>
</body>
</html>
```
--------------------------------------------------------------------------------
/docs/src/providers/posthog-provider.tsx:
--------------------------------------------------------------------------------
```typescript
'use client';
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react';
import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
if (typeof window !== 'undefined') {
const apiKey = process.env.NEXT_PUBLIC_POSTHOG_API_KEY;
if (apiKey) {
posthog.init(apiKey, {
api_host: '/docs/api/posthog',
ui_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
person_profiles: 'always',
capture_pageview: false,
capture_pageleave: true,
});
} else {
console.warn('[PostHog] API key not configured. Analytics will be disabled.');
}
}
export function PHProvider({ children }: { children: React.ReactNode }) {
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
export function PostHogPageView(): null {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
if (pathname) {
let url = window.origin + pathname;
if (searchParams && searchParams.toString()) {
url = url + `?${searchParams.toString()}`;
}
posthog.capture('$pageview', {
$current_url: url,
});
}
}, [pathname, searchParams]);
return null;
}
```
--------------------------------------------------------------------------------
/libs/lume/src/ContainerRegistry/ImagesPrinter.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
struct ImagesPrinter {
private struct Column: Sendable {
let header: String
let width: Int
let getValue: @Sendable (String) -> String
}
private static let columns: [Column] = [
Column(header: "name", width: 28) { $0.split(separator: ":").first.map(String.init) ?? $0 },
Column(header: "image_id", width: 16) { $0.split(separator: ":").last.map(String.init) ?? "-" }
]
static func print(images: [String]) {
if images.isEmpty {
Swift.print("No images found")
return
}
printHeader()
images.sorted().forEach(printImage)
}
private static func printHeader() {
let paddedHeaders = columns.map { $0.header.paddedToWidth($0.width) }
Swift.print(paddedHeaders.joined())
}
private static func printImage(_ image: String) {
let paddedColumns = columns.map { column in
column.getValue(image).paddedToWidth(column.width)
}
Swift.print(paddedColumns.joined())
}
}
private extension String {
func paddedToWidth(_ width: Int) -> String {
padding(toLength: width, withPad: " ", startingAt: 0)
}
}
```
--------------------------------------------------------------------------------
/libs/python/computer-server/tests/conftest.py:
--------------------------------------------------------------------------------
```python
"""Pytest configuration and shared fixtures for computer-server package tests.
This file contains shared fixtures and configuration for all computer-server tests.
Following SRP: This file ONLY handles test setup/teardown.
"""
from unittest.mock import AsyncMock, Mock, patch
import pytest
@pytest.fixture
def mock_websocket():
"""Mock WebSocket connection for testing.
Use this fixture to test WebSocket logic without real connections.
"""
websocket = AsyncMock()
websocket.send = AsyncMock()
websocket.recv = AsyncMock()
websocket.close = AsyncMock()
return websocket
@pytest.fixture
def mock_computer_interface():
"""Mock computer interface for server tests.
Use this fixture to test server logic without real computer operations.
"""
interface = AsyncMock()
interface.screenshot = AsyncMock(return_value=b"fake_screenshot")
interface.left_click = AsyncMock()
interface.type = AsyncMock()
interface.key = AsyncMock()
return interface
@pytest.fixture
def disable_telemetry(monkeypatch):
"""Disable telemetry for tests.
Use this fixture to ensure no telemetry is sent during tests.
"""
monkeypatch.setenv("CUA_TELEMETRY_DISABLED", "1")
```
--------------------------------------------------------------------------------
/docs/src/assets/discord-white.svg:
--------------------------------------------------------------------------------
```
<?xml version="1.0" encoding="UTF-8"?><svg id="Discord-Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126.644 96"><defs><style>.cls-1{fill:#fff;}</style></defs><path id="Discord-Symbol-White" class="cls-1" d="M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z"/></svg>
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/__init__.py:
--------------------------------------------------------------------------------
```python
"""
agent - Decorator-based Computer Use Agent with liteLLM integration
"""
import logging
import sys
# Import loops to register them
from . import loops
from .agent import ComputerAgent
from .decorators import register_agent
from .types import AgentResponse, Messages
__all__ = ["register_agent", "ComputerAgent", "Messages", "AgentResponse"]
__version__ = "0.4.0"
logger = logging.getLogger(__name__)
# Initialize telemetry when the package is imported
try:
# Import from core telemetry for basic functions
from core.telemetry import (
is_telemetry_enabled,
record_event,
)
# Check if telemetry is enabled
if is_telemetry_enabled():
logger.info("Telemetry is enabled")
# Record package initialization
record_event(
"module_init",
{
"module": "agent",
"version": __version__,
"python_version": sys.version,
},
)
else:
logger.info("Telemetry is disabled")
except ImportError as e:
# Telemetry not available
logger.warning(f"Telemetry not available: {e}")
except Exception as e:
# Other issues with telemetry
logger.warning(f"Error initializing telemetry: {e}")
```
--------------------------------------------------------------------------------
/docs/content/docs/macos-vm-cli-playbook/lumier/building-lumier.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Building Lumier
---
If you want to customize the Lumier container or build it from source, you can follow these steps:
```bash
# 1. Navigate to the Lumier directory
cd libs/lumier
# 2. Build the Docker image locally
docker build -t lumier-custom:latest .
# 3. Run your custom build
docker run -it --rm \
--name lumier-vm \
-p 8006:8006 \
-e VM_NAME=lumier-vm \
-e VERSION=ghcr.io/trycua/macos-sequoia-cua:latest \
-e CPU_CORES=4 \
-e RAM_SIZE=8192 \
lumier-custom:latest
```
### Customization Options
The Dockerfile provides several customization points:
1. **Base image**: The container uses Debian Bullseye Slim as the base. You can modify this if needed.
2. **Installed packages**: You can add or remove packages in the apt-get install list.
3. **Hooks**: Check the `/run/hooks/` directory for scripts that run at specific points during VM lifecycle.
4. **Configuration**: Review `/run/config/constants.sh` for default settings.
After making your modifications, you can build and push your custom image to your own Docker Hub repository:
```bash
# Build with a custom tag
docker build -t yourusername/lumier:custom .
# Push to Docker Hub (after docker login)
docker push yourusername/lumier:custom
```
```
--------------------------------------------------------------------------------
/libs/python/computer-server/tests/test_server.py:
--------------------------------------------------------------------------------
```python
"""Unit tests for computer-server package.
This file tests ONLY basic server functionality.
Following SRP: This file tests server initialization and basic operations.
All external dependencies are mocked.
"""
from unittest.mock import AsyncMock, Mock, patch
import pytest
class TestServerImports:
"""Test server module imports (SRP: Only tests imports)."""
def test_server_module_exists(self):
"""Test that server module can be imported."""
try:
import computer_server
assert computer_server is not None
except ImportError:
pytest.skip("computer_server module not installed")
class TestServerInitialization:
"""Test server initialization (SRP: Only tests initialization)."""
@pytest.mark.asyncio
async def test_server_can_be_imported(self):
"""Basic smoke test: verify server components can be imported."""
try:
from computer_server import server
assert server is not None
except ImportError:
pytest.skip("Server module not available")
except Exception as e:
# Some initialization errors are acceptable in unit tests
pytest.skip(f"Server initialization requires specific setup: {e}")
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/desktop-extension/run_server.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Wrapper script to ensure we use the correct Python with dependencies
# Try different Python paths in order of preference
PYTHON_PATHS=(
"/Users/yellcw/Documents/GitHub/cua/.venv/bin/python"
"/opt/homebrew/bin/python3"
"/usr/local/bin/python3"
"python3"
)
# Find the first Python that has the required packages
for python_path in "${PYTHON_PATHS[@]}"; do
if command -v "$python_path" >/dev/null 2>&1; then
# Check if it has the required packages
if "$python_path" -c "import mcp, anyio" >/dev/null 2>&1; then
echo "Using Python: $python_path" >&2
exec "$python_path" "$@"
fi
fi
done
# If no Python with packages found, try to install them
echo "No Python with required packages found. Attempting to install..." >&2
for python_path in "${PYTHON_PATHS[@]}"; do
if command -v "$python_path" >/dev/null 2>&1; then
echo "Installing packages with: $python_path" >&2
if "$python_path" -m pip install mcp anyio cua-agent[all] cua-computer >/dev/null 2>&1; then
echo "Packages installed successfully with: $python_path" >&2
exec "$python_path" "$@"
fi
fi
done
echo "Failed to find or install Python with required packages" >&2
exit 1
```
--------------------------------------------------------------------------------
/libs/typescript/agent/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "@trycua/agent",
"version": "0.1.0",
"packageManager": "[email protected]",
"description": "TypeScript SDK for CUA agent interaction",
"type": "module",
"license": "MIT",
"homepage": "https://github.com/trycua/cua/tree/main/libs/typescript/agent",
"bugs": {
"url": "https://github.com/trycua/cua/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/trycua/cua.git"
},
"author": "cua",
"files": [
"dist"
],
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"typecheck": "tsc --noEmit",
"release": "bumpp && pnpm publish",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@trycua/core": "^0.1.2",
"peerjs": "^1.5.4",
"pino": "^9.7.0"
},
"devDependencies": {
"@types/node": "^22.15.17",
"bumpp": "^10.1.0",
"happy-dom": "^20.0.11",
"tsdown": "^0.14.1",
"typescript": "^5.7.2",
"vitest": "^4.0.14"
}
}
```
--------------------------------------------------------------------------------
/libs/typescript/computer/tests/interface/index.test.ts:
--------------------------------------------------------------------------------
```typescript
import { describe, expect, it } from 'vitest';
import * as InterfaceExports from '../../src/interface/index.ts';
describe('Interface Module Exports', () => {
it('should export InterfaceFactory', () => {
expect(InterfaceExports.InterfaceFactory).toBeDefined();
expect(InterfaceExports.InterfaceFactory.createInterfaceForOS).toBeDefined();
});
it('should export BaseComputerInterface', () => {
expect(InterfaceExports.BaseComputerInterface).toBeDefined();
});
it('should export MacOSComputerInterface', () => {
expect(InterfaceExports.MacOSComputerInterface).toBeDefined();
});
it('should export LinuxComputerInterface', () => {
expect(InterfaceExports.LinuxComputerInterface).toBeDefined();
});
it('should export WindowsComputerInterface', () => {
expect(InterfaceExports.WindowsComputerInterface).toBeDefined();
});
it('should export all expected interfaces', () => {
const expectedExports = [
'InterfaceFactory',
'BaseComputerInterface',
'MacOSComputerInterface',
'LinuxComputerInterface',
'WindowsComputerInterface',
];
const actualExports = Object.keys(InterfaceExports);
for (const exportName of expectedExports) {
expect(actualExports).toContain(exportName);
}
});
});
```
--------------------------------------------------------------------------------
/docs/content/docs/cli-playbook/index.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Getting Started
description: Install and set up the CUA CLI
---
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
import { Callout } from 'fumadocs-ui/components/callout';
The Cua CLI is a command-line tool for managing your Cua cloud sandboxes. Create, start, stop, and connect to sandboxes directly from your terminal.
## Installation
<Tabs items={['macOS / Linux', 'Windows']}>
<Tab value="macOS / Linux">
```bash
curl -LsSf https://cua.ai/cli/install.sh | sh
```
</Tab>
<Tab value="Windows">
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://cua.ai/cli/install.ps1 | iex"
```
</Tab>
</Tabs>
This installs [Bun](https://bun.sh) and the CUA CLI. Verify with:
```bash
cua --help
```
## Authentication
Login to your CUA account:
```bash
# Browser-based login
cua auth login
# Or with API key
cua auth login --api-key sk-your-api-key-here
```
Generate a `.env` file for your project:
```bash
cua auth env
```
## Quick Start
```bash
# Create a sandbox
cua create --os linux --size small --region north-america
# List sandboxes
cua list
# Open VNC in browser
cua vnc my-sandbox
# Stop a sandbox
cua stop my-sandbox
```
## Next Steps
- [Command Reference](/cli-playbook/commands) - Full list of available commands
```
--------------------------------------------------------------------------------
/docs/content/docs/macos-vm-cli-playbook/lumier/index.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Lumier
description: Reference for the current version of the Lumier library.
github:
- https://github.com/trycua/cua/tree/main/libs/lumier
---
**Lumier** is an interface for running macOS virtual machines with minimal setup. It uses Docker as a packaging system to deliver a pre-configured environment that connects to the `lume` virtualization service running on your host machine. With Lumier, you get:
- A ready-to-use macOS or Linux virtual machine in minutes
- Browser-based VNC access to your VM
- Easy file sharing between your host and VM
- Simple configuration through environment variables
## How It Works
<Callout title="Note">
We're using Docker primarily as a convenient delivery mechanism, not as an isolation layer. Unlike
traditional Docker containers, Lumier leverages the Apple Virtualization Framework (Apple Vz)
through the `lume` CLI to create true virtual machines.
</Callout>
Here's what's happening behind the scenes:
1. The Docker container provides a consistent environment to run the Lumier interface
2. Lumier connects to the Lume service running on your host Mac
3. Lume uses Apple's Virtualization Framework to create a true macOS virtual machine
4. The VM runs with hardware acceleration using your Mac's native virtualization capabilities
```
--------------------------------------------------------------------------------
/libs/typescript/computer/src/interface/factory.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Factory for creating computer interfaces.
*/
import type { OSType } from '../types';
import type { BaseComputerInterface } from './base';
import { LinuxComputerInterface } from './linux';
import { MacOSComputerInterface } from './macos';
import { WindowsComputerInterface } from './windows';
export const InterfaceFactory = {
/**
* Create an interface for the specified OS.
*
* @param os Operating system type ('macos', 'linux', or 'windows')
* @param ipAddress IP address of the computer to control
* @param apiKey Optional API key for cloud authentication
* @param vmName Optional VM name for cloud authentication
* @returns The appropriate interface for the OS
* @throws Error if the OS type is not supported
*/
createInterfaceForOS(
os: OSType,
ipAddress: string,
apiKey?: string,
vmName?: string
): BaseComputerInterface {
switch (os) {
case 'macos':
return new MacOSComputerInterface(ipAddress, 'lume', 'lume', apiKey, vmName);
case 'linux':
return new LinuxComputerInterface(ipAddress, 'lume', 'lume', apiKey, vmName);
case 'windows':
return new WindowsComputerInterface(ipAddress, 'lume', 'lume', apiKey, vmName);
default:
throw new Error(`Unsupported OS type: ${os}`);
}
},
};
```
--------------------------------------------------------------------------------
/docs/src/components/hero.tsx:
--------------------------------------------------------------------------------
```typescript
export function Hero({ children }: { children: React.ReactNode }) {
return (
<div className="not-prose relative mb-12 overflow-hidden rounded-xl border border-fd-border bg-gradient-to-br from-fd-background via-fd-muted/30 to-fd-muted/50 p-8 shadow-lg md:p-12 lg:p-16">
{/* Background Pattern */}
<div className="pointer-events-none absolute inset-0">
{/* Grid */}
<svg
className="absolute h-full w-full text-fd-foreground"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<pattern id="hero-grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path
d="M 40 0 L 0 0 0 40"
fill="none"
stroke="currentColor"
strokeWidth="0.5"
opacity="0.1"
/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#hero-grid)" />
</svg>
{/* Subtle glow effects */}
<div className="absolute -right-20 -top-20 h-96 w-96 rounded-full bg-fd-primary/5 blur-3xl" />
<div className="absolute -bottom-32 -left-20 h-96 w-96 rounded-full bg-fd-primary/5 blur-3xl" />
</div>
{/* Content */}
<div className="relative z-10">{children}</div>
</div>
);
}
```
--------------------------------------------------------------------------------
/libs/lume/Package.swift:
--------------------------------------------------------------------------------
```swift
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "lume",
platforms: [
.macOS(.v14)
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.1"),
.package(url: "https://github.com/apple/swift-format.git", branch: ("release/5.10")),
.package(url: "https://github.com/apple/swift-atomics.git", .upToNextMajor(from: "1.2.0")),
.package(url: "https://github.com/mhdhejazi/Dynamic", branch: "master")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "lume",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Atomics", package: "swift-atomics"),
.product(name: "Dynamic", package: "Dynamic")
],
path: "src"),
.testTarget(
name: "lumeTests",
dependencies: [
"lume"
],
path: "tests")
]
)
```
--------------------------------------------------------------------------------
/docs/src/components/cookie-consent.tsx:
--------------------------------------------------------------------------------
```typescript
'use client';
import { useEffect, useState } from 'react';
import posthog from 'posthog-js';
export function CookieConsent() {
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
// Check if user has already accepted cookies
const hasAccepted = localStorage.getItem('cookie-consent');
if (!hasAccepted) {
setIsVisible(true);
}
}, []);
const handleAccept = () => {
localStorage.setItem('cookie-consent', 'accepted');
setIsVisible(false);
// Track cookie acceptance
posthog.capture('cookie_consent_accepted', {
page: window.location.pathname,
});
};
if (!isVisible) return null;
return (
<div className="fixed bottom-0 left-0 right-0 z-50 bg-fd-background border-t border-fd-border shadow-lg">
<div className="container mx-auto px-4 py-2 flex flex-col sm:flex-row items-center justify-between gap-3">
<p className="text-xs text-fd-muted-foreground">
This site uses cookies for website functionality, analytics, and personalized content.
</p>
<button
onClick={handleAccept}
className="px-4 py-1 text-xs bg-fd-primary text-fd-primary-foreground rounded hover:opacity-90 transition-opacity whitespace-nowrap"
>
Okay
</button>
</div>
</div>
);
}
```
--------------------------------------------------------------------------------
/docs/src/components/mermaid.tsx:
--------------------------------------------------------------------------------
```typescript
'use client';
import { useEffect, useId, useRef, useState } from 'react';
import { useTheme } from 'next-themes';
export function Mermaid({ chart }: { chart: string }) {
const id = useId();
const [svg, setSvg] = useState('');
const containerRef = useRef<HTMLDivElement>(null);
const currentChartRef = useRef<string>(null);
const { resolvedTheme } = useTheme();
useEffect(() => {
if (currentChartRef.current === chart || !containerRef.current) return;
const container = containerRef.current;
currentChartRef.current = chart;
async function renderChart() {
const { default: mermaid } = await import('mermaid');
try {
// configure mermaid
mermaid.initialize({
startOnLoad: false,
securityLevel: 'loose',
fontFamily: 'inherit',
themeCSS: 'margin: 1.5rem auto 0;',
theme: resolvedTheme === 'dark' ? 'dark' : 'default',
});
const { svg, bindFunctions } = await mermaid.render(id, chart.replaceAll('\\n', '\n'));
bindFunctions?.(container);
setSvg(svg);
} catch (error) {
console.error('Error while rendering mermaid', error);
}
}
void renderChart();
}, [chart, id, resolvedTheme]);
return <div ref={containerRef} dangerouslySetInnerHTML={{ __html: svg }} />;
}
```
--------------------------------------------------------------------------------
/docs/src/app/layout.tsx:
--------------------------------------------------------------------------------
```typescript
import './global.css';
import { RootProvider } from 'fumadocs-ui/provider';
import { Geist, Geist_Mono } from 'next/font/google';
import type { ReactNode } from 'react';
import { PHProvider, PostHogPageView } from '@/providers/posthog-provider';
import { AnalyticsTracker } from '@/components/analytics-tracker';
import { CookieConsent } from '@/components/cookie-consent';
import { Footer } from '@/components/footer';
import { Suspense } from 'react';
const geist = Geist({
subsets: ['latin'],
variable: '--font-geist-sans',
});
const geistMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-geist-mono',
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html
lang="en"
className={`${geist.variable} ${geistMono.variable} font-sans`}
suppressHydrationWarning
>
<head>
<link rel="icon" href="/docs/favicon.ico" sizes="any" />
</head>
<body className="flex min-h-screen flex-col">
<PHProvider>
<Suspense fallback={null}>
<PostHogPageView />
</Suspense>
<AnalyticsTracker />
<RootProvider search={{ options: { api: '/docs/api/search' } }}>{children}</RootProvider>
<Footer />
<CookieConsent />
</PHProvider>
</body>
</html>
);
}
```
--------------------------------------------------------------------------------
/.github/workflows/npm-publish-core.yml:
--------------------------------------------------------------------------------
```yaml
name: Publish @trycua/core to npm
on:
push:
branches: main
jobs:
publish:
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 24.x
uses: actions/setup-node@v4
with:
node-version: "24.x"
registry-url: "https://registry.npmjs.org"
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10
- name: Check if version changed
id: check-version
uses: EndBug/version-check@v2
with:
file-name: libs/typescript/core/package.json
diff-search: true
- name: Install dependencies
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/core
run: pnpm install --frozen-lockfile
- name: Build package
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/core
run: pnpm run build --if-present
- name: Publish to npm
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/core
run: pnpm publish --access public --no-git-checks
env:
NPM_CONFIG_PROVENANCE: true
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
```yaml
name: Lint & Format Check
on:
pull_request:
push:
branches:
- main
jobs:
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.12
- name: Install Python dependencies
run: |
pip install uv
uv sync
- name: Install Node dependencies
run: |
pnpm install --frozen-lockfile
pnpm -C libs/typescript install --frozen-lockfile
# Python checks (isort, black, ruff, mypy)
- name: Python lint & typecheck
run: |
uv run isort --check-only .
uv run black --check .
uv run ruff check .
# Temporarily disabled due to untyped codebase
# uv run mypy .
# TypeScript type check
- name: TypeScript typecheck
run: node ./scripts/typescript-typecheck.js
# JS/TS/Markdown/YAML checks
- name: Prettier check
run: pnpm prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"
```
--------------------------------------------------------------------------------
/libs/typescript/computer/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "@trycua/computer",
"version": "0.1.4",
"packageManager": "[email protected]",
"description": "Typescript SDK for Cua computer interaction",
"type": "module",
"license": "MIT",
"homepage": "https://github.com/trycua/cua/tree/feature/computer/typescript/libs/typescript/computer",
"bugs": {
"url": "https://github.com/trycua/cua/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/trycua/cua.git"
},
"author": "cua",
"files": [
"dist"
],
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"typecheck": "tsc --noEmit",
"release": "bumpp && pnpm publish",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@trycua/core": "^0.1.2",
"pino": "^9.7.0",
"ws": "^8.18.0"
},
"devDependencies": {
"@types/node": "^22.15.17",
"@types/ws": "^8.18.1",
"bumpp": "^10.1.0",
"happy-dom": "^20.0.11",
"tsdown": "^0.11.9",
"tsx": "^4.19.4",
"typescript": "^5.8.3",
"vitest": "^4.0.14"
}
}
```
--------------------------------------------------------------------------------
/libs/python/bench-ui/tests/test_port_detection.py:
--------------------------------------------------------------------------------
```python
import time
import psutil
import pytest
from bench_ui import execute_javascript, launch_window
from bench_ui.api import _pid_to_port
HTML = """
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Bench UI Test</title>
</head>
<body>
<div id="t">hello-world</div>
</body>
</html>
"""
def test_execute_js_after_clearing_port_mapping():
# Skip if pywebview backend is unavailable on this machine
pywebview = pytest.importorskip("webview")
pid = launch_window(html=HTML, title="Bench UI Test", width=400, height=300)
try:
# Give a brief moment for window to render and server to start
time.sleep(1.0)
# Sanity: mapping should exist initially
assert pid in _pid_to_port
# Clear the cached mapping to simulate a fresh process lookup
del _pid_to_port[pid]
# Now execute JS; this should succeed by detecting the port via psutil
result = execute_javascript(pid, "document.querySelector('#t')?.textContent")
assert result == "hello-world"
finally:
# Best-effort cleanup of the child process
try:
p = psutil.Process(pid)
p.terminate()
try:
p.wait(timeout=3)
except psutil.TimeoutExpired:
p.kill()
except Exception:
pass
```
--------------------------------------------------------------------------------
/libs/typescript/core/tests/telemetry.test.ts:
--------------------------------------------------------------------------------
```typescript
import { beforeEach, describe, expect, it } from 'vitest';
import { Telemetry } from '../src/';
describe('Telemetry', () => {
let telemetry: Telemetry;
beforeEach(() => {
process.env.CUA_TELEMETRY_ENABLED = '';
telemetry = new Telemetry();
});
describe('telemetry.enabled', () => {
it('should return false when CUA_TELEMETRY_ENABLED is false', () => {
process.env.CUA_TELEMETRY_ENABLED = 'false';
telemetry = new Telemetry();
expect(telemetry.enabled).toBe(false);
});
it('should return false when CUA_TELEMETRY_ENABLED is 0', () => {
process.env.CUA_TELEMETRY_ENABLED = '0';
telemetry = new Telemetry();
expect(telemetry.enabled).toBe(false);
});
it('should return true when CUA_TELEMETRY_ENABLED is not set (default)', () => {
delete process.env.CUA_TELEMETRY_ENABLED;
telemetry = new Telemetry();
expect(telemetry.enabled).toBe(true);
});
it('should return true when CUA_TELEMETRY_ENABLED is true', () => {
process.env.CUA_TELEMETRY_ENABLED = 'true';
telemetry = new Telemetry();
expect(telemetry.enabled).toBe(true);
});
it('should return true when CUA_TELEMETRY_ENABLED is 1', () => {
process.env.CUA_TELEMETRY_ENABLED = '1';
telemetry = new Telemetry();
expect(telemetry.enabled).toBe(true);
});
});
});
```
--------------------------------------------------------------------------------
/libs/typescript/core/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "@trycua/core",
"version": "0.1.3",
"packageManager": "[email protected]",
"description": "Typescript SDK for Cua core.",
"type": "module",
"license": "MIT",
"homepage": "https://github.com/trycua/cua/tree/feature/computer/typescript/libs/typescript/computer",
"bugs": {
"url": "https://github.com/trycua/cua/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/trycua/cua.git"
},
"author": "cua",
"files": [
"dist"
],
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"typecheck": "tsc --noEmit",
"release": "bumpp && pnpm publish",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@types/uuid": "^10.0.0",
"pino": "^9.7.0",
"posthog-node": "^5.14.1",
"uuid": "^11.1.0"
},
"devDependencies": {
"@types/node": "^22.15.17",
"@types/ws": "^8.18.1",
"bumpp": "^10.1.0",
"happy-dom": "^20.0.11",
"tsdown": "^0.11.9",
"tsx": "^4.19.4",
"typescript": "^5.8.3",
"vitest": "^4.0.14"
}
}
```
--------------------------------------------------------------------------------
/.github/workflows/npm-publish-computer.yml:
--------------------------------------------------------------------------------
```yaml
name: Publish @trycua/computer to npm
on:
push:
branches: main
jobs:
publish:
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js 24.x
uses: actions/setup-node@v4
with:
node-version: "24.x"
registry-url: "https://registry.npmjs.org"
- name: Setup pnpm 10
uses: pnpm/action-setup@v4
with:
version: 10
- name: Check if version changed
id: check-version
uses: EndBug/version-check@v2
with:
file-name: libs/typescript/computer/package.json
diff-search: true
- name: Install dependencies
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/computer
run: pnpm install --frozen-lockfile
- name: Build package
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/computer
run: pnpm run build --if-present
- name: Publish to npm
if: steps.check-version.outputs.changed == 'true'
working-directory: ./libs/typescript/computer
run: pnpm publish --access public --no-git-checks
env:
NPM_CONFIG_PROVENANCE: true
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/tests/conftest.py:
--------------------------------------------------------------------------------
```python
"""Pytest configuration and shared fixtures for mcp-server package tests.
This file contains shared fixtures and configuration for all mcp-server tests.
Following SRP: This file ONLY handles test setup/teardown.
"""
from unittest.mock import AsyncMock, Mock, patch
import pytest
@pytest.fixture
def mock_mcp_context():
"""Mock MCP context for testing.
Use this fixture to test MCP server logic without real MCP connections.
"""
context = AsyncMock()
context.request_context = AsyncMock()
context.session = Mock()
context.session.send_resource_updated = AsyncMock()
return context
@pytest.fixture
def mock_computer():
"""Mock Computer instance for MCP server tests.
Use this fixture to test MCP logic without real Computer operations.
"""
computer = AsyncMock()
computer.interface = AsyncMock()
computer.interface.screenshot = AsyncMock(return_value=b"fake_screenshot")
computer.interface.left_click = AsyncMock()
computer.interface.type = AsyncMock()
# Mock context manager
computer.__aenter__ = AsyncMock(return_value=computer)
computer.__aexit__ = AsyncMock()
return computer
@pytest.fixture
def disable_telemetry(monkeypatch):
"""Disable telemetry for tests.
Use this fixture to ensure no telemetry is sent during tests.
"""
monkeypatch.setenv("CUA_TELEMETRY_DISABLED", "1")
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/callbacks/trajectories.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Trajectories
description: Recording and viewing agent conversation trajectories
---
# Trajectory Saving Callback
The TrajectorySaverCallback records complete agent conversations including messages, actions, and screenshots for debugging and analysis.
## Callbacks Example
```python
from agent.callbacks import TrajectorySaverCallback
agent = ComputerAgent(
model="anthropic/claude-sonnet-4-5-20250929",
tools=[computer],
callbacks=[
TrajectorySaverCallback(
trajectory_dir="my_trajectories",
save_screenshots=True
)
]
)
```
## Shorthand
```python
agent = ComputerAgent(
model="anthropic/claude-sonnet-4-5-20250929",
trajectory_dir="trajectories", # Auto-save trajectories
tools=[computer]
)
```
## View Trajectories Online
View trajectories in the browser at:
**[cua.ai/trajectory-viewer](https://cua.ai/trajectory-viewer)**
The viewer provides:
- Interactive conversation replay
- Screenshot galleries
- No data collection
## Trajectory Structure
Trajectories are saved with:
- Complete conversation history
- Usage statistics and costs
- Timestamps and metadata
- Screenshots and computer actions
Each trajectory contains:
- **metadata.json**: Run info, timestamps, usage stats (`total_tokens`, `response_cost`)
- **turn_000/**: Turn-by-turn conversation history (api calls, responses, computer calls, screenshots)
```
--------------------------------------------------------------------------------
/examples/utils.py:
--------------------------------------------------------------------------------
```python
"""Utility functions for example scripts."""
import os
import signal
import sys
from pathlib import Path
from typing import Optional
def load_env_file(path: Path) -> bool:
"""Load environment variables from a file.
Args:
path: Path to the .env file
Returns:
True if file was loaded successfully, False otherwise
"""
if not path.exists():
return False
print(f"Loading environment from {path}")
with open(path, "r") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
key, value = line.split("=", 1)
os.environ[key] = value
return True
def load_dotenv_files():
"""Load environment variables from .env files.
Tries to load from .env.local first, then .env if .env.local doesn't exist.
"""
# Get the project root directory (parent of the examples directory)
project_root = Path(__file__).parent.parent
# Try loading .env.local first, then .env if .env.local doesn't exist
env_local_path = project_root / ".env.local"
env_path = project_root / ".env"
# Load .env.local if it exists, otherwise try .env
if not load_env_file(env_local_path):
load_env_file(env_path)
def handle_sigint(signum, frame):
"""Handle SIGINT (Ctrl+C) gracefully."""
print("\nExiting gracefully...")
sys.exit(0)
```
--------------------------------------------------------------------------------
/libs/lume/Development.md:
--------------------------------------------------------------------------------
```markdown
# Development Guide
This guide will help you set up your development environment and understand the process for contributing code to lume.
## Environment Setup
Lume development requires:
- Swift 6 or higher
- Xcode 15 or higher
- macOS Sequoia 15.2 or higher
- (Optional) VS Code with Swift extension
If you're working on Lume in the context of the Cua monorepo, we recommend using the dedicated VS Code workspace configuration:
```bash
# Open VS Code workspace from the root of the monorepo
code .vscode/lume.code-workspace
```
This workspace is preconfigured with Swift language support, build tasks, and debug configurations.
## Setting Up the Repository Locally
1. **Fork the Repository**: Create your own fork of lume
2. **Clone the Repository**:
```bash
git clone https://github.com/trycua/lume.git
cd lume
```
3. **Install Dependencies**:
```bash
swift package resolve
```
4. **Build the Project**:
```bash
swift build
```
## Development Workflow
1. Create a new branch for your changes
2. Make your changes
3. Run the tests: `swift test`
4. Build and test your changes locally
5. Commit your changes with clear commit messages
## Submitting Pull Requests
1. Push your changes to your fork
2. Open a Pull Request with:
- A clear title and description
- Reference to any related issues
- Screenshots or logs if relevant
3. Respond to any feedback from maintainers
```
--------------------------------------------------------------------------------
/libs/lume/src/Commands/Serve.swift:
--------------------------------------------------------------------------------
```swift
import ArgumentParser
import Foundation
struct Serve: AsyncParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Start the VM management server"
)
@Option(help: "Port to listen on")
var port: UInt16 = 7777
func run() async throws {
let server = await Server(port: port)
Logger.info("Starting server", metadata: ["port": "\(port)"])
// Using custom error handling to prevent ArgumentParser from printing additional error messages
do {
try await server.start()
} catch let error as PortError {
// For port errors, just log once with the suggestion
let suggestedPort = port + 1
// Create a user-friendly error message that includes the suggestion
let message = """
\(error.localizedDescription)
Try using a different port: lume serve --port \(suggestedPort)
"""
// Log the message (without the "ERROR:" prefix that ArgumentParser will add)
Logger.error(message)
// Exit with a custom code to prevent ArgumentParser from printing the error again
Foundation.exit(1)
} catch {
// For other errors, log once
Logger.error("Failed to start server", metadata: ["error": error.localizedDescription])
throw error
}
}
}
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/adapters/models/__init__.py:
--------------------------------------------------------------------------------
```python
from typing import Optional
try:
from transformers import AutoConfig
HF_AVAILABLE = True
except ImportError:
HF_AVAILABLE = False
from .generic import GenericHFModel
from .internvl import InternVLModel
from .opencua import OpenCUAModel
from .qwen2_5_vl import Qwen2_5_VLModel
def load_model(model_name: str, device: str = "auto", trust_remote_code: bool = False):
"""Factory function to load and return the right model handler instance.
- If the underlying transformers config class matches OpenCUA, return OpenCUAModel
- Otherwise, return GenericHFModel
"""
if not HF_AVAILABLE:
raise ImportError(
'HuggingFace transformers dependencies not found. Install with: pip install "cua-agent[uitars-hf]"'
)
cfg = AutoConfig.from_pretrained(model_name, trust_remote_code=trust_remote_code)
cls = cfg.__class__.__name__
print(f"cls: {cls}")
if "OpenCUA" in cls:
return OpenCUAModel(
model_name=model_name, device=device, trust_remote_code=trust_remote_code
)
elif "Qwen2_5_VL" in cls:
return Qwen2_5_VLModel(
model_name=model_name, device=device, trust_remote_code=trust_remote_code
)
elif "InternVL" in cls:
return InternVLModel(
model_name=model_name, device=device, trust_remote_code=trust_remote_code
)
return GenericHFModel(model_name=model_name, device=device, trust_remote_code=trust_remote_code)
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/computers/__init__.py:
--------------------------------------------------------------------------------
```python
"""
Computer handler factory and interface definitions.
This module provides a factory function to create computer handlers from different
computer interface types, supporting both the ComputerHandler protocol and the
Computer library interface.
"""
from computer import Computer as cuaComputer
from .base import AsyncComputerHandler
from .cua import cuaComputerHandler
from .custom import CustomComputerHandler
def is_agent_computer(computer):
"""Check if the given computer is a ComputerHandler or CUA Computer."""
return (
isinstance(computer, AsyncComputerHandler)
or isinstance(computer, cuaComputer)
or (isinstance(computer, dict))
) # and "screenshot" in computer)
async def make_computer_handler(computer):
"""
Create a computer handler from a computer interface.
Args:
computer: Either a ComputerHandler instance, Computer instance, or dict of functions
Returns:
ComputerHandler: A computer handler instance
Raises:
ValueError: If the computer type is not supported
"""
if isinstance(computer, AsyncComputerHandler):
return computer
if isinstance(computer, cuaComputer):
computer_handler = cuaComputerHandler(computer)
await computer_handler._initialize()
return computer_handler
if isinstance(computer, dict):
return CustomComputerHandler(computer)
raise ValueError(f"Unsupported computer type: {type(computer)}")
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/tests/test_mcp_server.py:
--------------------------------------------------------------------------------
```python
"""Unit tests for mcp-server package.
This file tests ONLY basic MCP server functionality.
Following SRP: This file tests MCP server initialization.
All external dependencies are mocked.
"""
from unittest.mock import AsyncMock, Mock, patch
import pytest
class TestMCPServerImports:
"""Test MCP server module imports (SRP: Only tests imports)."""
def test_mcp_server_module_exists(self):
"""Test that mcp_server module can be imported."""
try:
import mcp_server
assert mcp_server is not None
except ImportError:
pytest.skip("mcp_server module not installed")
except SystemExit:
pytest.skip("MCP dependencies (mcp.server.fastmcp) not available")
class TestMCPServerInitialization:
"""Test MCP server initialization (SRP: Only tests initialization)."""
@pytest.mark.asyncio
async def test_mcp_server_can_be_imported(self):
"""Basic smoke test: verify MCP server components can be imported."""
try:
from mcp_server import server
assert server is not None
except ImportError:
pytest.skip("MCP server module not available")
except SystemExit:
pytest.skip("MCP dependencies (mcp.server.fastmcp) not available")
except Exception as e:
# Some initialization errors are acceptable in unit tests
pytest.skip(f"MCP server initialization requires specific setup: {e}")
```
--------------------------------------------------------------------------------
/docs/content/docs/computer-sdk/computer-server/REST-API.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: REST API Reference
description: Reference for the /cmd REST endpoint of the Computer Server.
---
# REST API Reference
The Computer Server exposes a single REST endpoint for command execution:
- `http://localhost:8000/cmd`
- `https://your-container.containers.cloud.trycua.com:8443/cmd` (cloud)
## POST /cmd
- Accepts commands as JSON in the request body
- Returns results as a streaming response (text/event-stream)
### Request Format
```json
{
"command": "<command_name>",
"params": { ... }
}
```
### Required Headers (for cloud containers)
- `X-Container-Name`: Name of the container (cloud only)
- `X-API-Key`: API key for authentication (cloud only)
### Example Request (Python)
```python
import requests
url = "http://localhost:8000/cmd"
body = {"command": "screenshot", "params": {}}
resp = requests.post(url, json=body)
print(resp.text)
```
### Example Request (Cloud)
```python
import requests
url = "https://your-container.containers.cloud.trycua.com:8443/cmd"
headers = {
"X-Container-Name": "your-container",
"X-API-Key": "your-api-key"
}
body = {"command": "screenshot", "params": {}}
resp = requests.post(url, json=body, headers=headers)
print(resp.text)
```
### Response Format
Streaming text/event-stream with JSON objects, e.g.:
```
data: {"success": true, "content": "..."}
data: {"success": false, "error": "..."}
```
### Supported Commands
See [Commands Reference](./Commands) for the full list of commands and parameters.
```
--------------------------------------------------------------------------------
/libs/kasm/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
FROM kasmweb/core-ubuntu-jammy:1.17.0
USER root
ENV HOME=/home/kasm-default-profile
ENV STARTUPDIR=/dockerstartup
ENV INST_SCRIPTS=$STARTUPDIR/install
WORKDIR $HOME
######### Customize Container Here ###########
# Installing python, pip, and libraries
RUN apt-get update
RUN apt install -y wget build-essential libncursesw5-dev libssl-dev \
libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev
RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt install -y python3.11 python3-pip python3-tk python3-dev \
gnome-screenshot wmctrl ffmpeg socat xclip
RUN pip install cua-computer-server
# Install Firefox
ENV DEBIAN_FRONTEND=noninteractive \
INST_DIR=$STARTUPDIR/install
COPY ./src/ $INST_DIR
RUN bash ${INST_DIR}/ubuntu/install/firefox/install_firefox.sh
# Disable SSL requirement
RUN sed -i 's/require_ssl: true/require_ssl: false/g' /usr/share/kasmvnc/kasmvnc_defaults.yaml
RUN sed -i 's/-sslOnly//g' /dockerstartup/vnc_startup.sh
# Running the python script on startup
RUN echo "/usr/bin/python3 -m computer_server" > $STARTUPDIR/custom_startup.sh \
&& chmod +x $STARTUPDIR/custom_startup.sh
# Enable sudo support for kasm-user
RUN echo "kasm-user:password" | chpasswd
RUN usermod -aG sudo kasm-user
RUN echo "kasm-user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
######### End Customizations ###########
RUN chown 1000:0 $HOME
RUN $STARTUPDIR/set_user_permission.sh $HOME
ENV HOME=/home/kasm-user
WORKDIR $HOME
RUN mkdir -p $HOME && chown -R 1000:0 $HOME
USER 1000
```
--------------------------------------------------------------------------------
/examples/winsandbox_example.py:
--------------------------------------------------------------------------------
```python
"""Example of using the Windows Sandbox computer provider.
Learn more at: https://learn.microsoft.com/en-us/windows/security/application-security/application-isolation/windows-sandbox/
"""
import asyncio
from computer import Computer
async def main():
"""Test the Windows Sandbox provider."""
# Create a computer instance using Windows Sandbox
computer = Computer(
provider_type="winsandbox",
os_type="windows",
memory="4GB",
# ephemeral=True, # Always true for Windows Sandbox
)
try:
print("Starting Windows Sandbox...")
await computer.run()
print("Windows Sandbox is ready!")
print(f"IP Address: {await computer.get_ip()}")
# Test basic functionality
print("Testing basic functionality...")
screenshot = await computer.interface.screenshot()
print(f"Screenshot taken: {len(screenshot)} bytes")
# Test running a command
print("Testing command execution...")
result = await computer.interface.run_command("echo Hello from Windows Sandbox!")
print(f"Command output: {result.stdout}")
print("Press any key to continue...")
input()
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
finally:
print("Stopping Windows Sandbox...")
await computer.stop()
print("Windows Sandbox stopped.")
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------------------------------------------------------
/libs/python/agent/agent/callbacks/prompt_instructions.py:
--------------------------------------------------------------------------------
```python
"""
Prompt instructions callback.
This callback allows simple prompt engineering by pre-pending a user
instructions message to the start of the conversation before each LLM call.
Usage:
from agent.callbacks import PromptInstructionsCallback
agent = ComputerAgent(
model="openai/computer-use-preview",
callbacks=[PromptInstructionsCallback("Follow these rules...")]
)
"""
from typing import Any, Dict, List, Optional
from .base import AsyncCallbackHandler
class PromptInstructionsCallback(AsyncCallbackHandler):
"""
Prepend a user instructions message to the message list.
This is a minimal, non-invasive way to guide the agent's behavior without
modifying agent loops or tools. It works with any provider/loop since it
only alters the messages array before sending to the model.
"""
def __init__(self, instructions: Optional[str]) -> None:
self.instructions = instructions
async def on_llm_start(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
# Pre-pend instructions message
if not self.instructions:
return messages
# Ensure we don't duplicate if already present at the front
if messages and isinstance(messages[0], dict):
first = messages[0]
if first.get("role") == "user" and first.get("content") == self.instructions:
return messages
return [
{"role": "user", "content": self.instructions},
] + messages
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/desktop-extension/setup.py:
--------------------------------------------------------------------------------
```python
#!/usr/bin/env python3
"""
Setup script for CUA Desktop Extension
Installs required dependencies if not available
"""
import subprocess
import sys
def check_and_install_package(package_name, import_name=None):
"""Check if a package is available, install if not."""
if import_name is None:
import_name = package_name
try:
__import__(import_name)
print(f"✓ {package_name} is available")
return True
except ImportError:
print(f"⚠ {package_name} not found, installing...")
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", package_name])
print(f"✓ {package_name} installed successfully")
return True
except subprocess.CalledProcessError as e:
print(f"✗ Failed to install {package_name}: {e}")
return False
def main():
"""Install required packages."""
print("Setting up CUA Desktop Extension dependencies...")
# Required packages
packages = [
("mcp", "mcp"),
("anyio", "anyio"),
("cua-agent[all]", "agent"),
("cua-computer", "computer"),
]
all_installed = True
for package, import_name in packages:
if not check_and_install_package(package, import_name):
all_installed = False
if all_installed:
print("✓ All dependencies are ready!")
return 0
else:
print("✗ Some dependencies failed to install")
return 1
if __name__ == "__main__":
sys.exit(main())
```
--------------------------------------------------------------------------------
/libs/python/mcp-server/scripts/start_mcp_server.sh:
--------------------------------------------------------------------------------
```bash
#!/usr/bin/env bash
set -Eeuo pipefail
# --- Resolve repo root from this script's location ---
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
CUA_REPO_DIR="$( cd "$SCRIPT_DIR/../../../.." &> /dev/null && pwd )"
# --- Choose a Python interpreter (prefer repo-root venv) ---
CANDIDATES=(
"$CUA_REPO_DIR/.venv/bin/python"
"$CUA_REPO_DIR/libs/.venv/bin/python"
"$(command -v python3 || true)"
"$(command -v python || true)"
)
PYTHON_PATH=""
for p in "${CANDIDATES[@]}"; do
if [[ -n "$p" && -x "$p" ]]; then
PYTHON_PATH="$p"
break
fi
done
if [[ -z "${PYTHON_PATH}" ]]; then
>&2 echo "[cua-mcp] ERROR: No suitable Python found. Tried:"
for p in "${CANDIDATES[@]}"; do >&2 echo " - $p"; done
>&2 echo "[cua-mcp] Tip: create venv: python3 -m venv $CUA_REPO_DIR/.venv && \"$CUA_REPO_DIR/.venv/bin/pip\" install -e \"$CUA_REPO_DIR/libs/python/mcp-server\""
exit 127
fi
# --- Export PYTHONPATH so module imports work during dev ---
export PYTHONPATH="$CUA_REPO_DIR/libs/python/mcp-server:$CUA_REPO_DIR/libs/python/agent:$CUA_REPO_DIR/libs/python/computer:$CUA_REPO_DIR/libs/python/core:$CUA_REPO_DIR/libs/python/pylume"
# --- Helpful startup log for Claude's mcp.log ---
>&2 echo "[cua-mcp] using python: $PYTHON_PATH"
>&2 echo "[cua-mcp] repo dir : $CUA_REPO_DIR"
>&2 echo "[cua-mcp] PYTHONPATH : $PYTHONPATH"
if [[ -n "${CUA_MODEL_NAME:-}" ]]; then
>&2 echo "[cua-mcp] CUA_MODEL_NAME=$CUA_MODEL_NAME"
fi
# --- Run the MCP server module ---
exec "$PYTHON_PATH" -m mcp_server.server
```
--------------------------------------------------------------------------------
/libs/qemu-docker/linux/src/entry.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
cleanup() {
echo "Received signal, shutting down gracefully..."
if [ -n "$VM_PID" ]; then
kill -TERM "$VM_PID" 2>/dev/null
wait "$VM_PID" 2>/dev/null
fi
exit 0
}
# Install trap for signals
trap cleanup SIGTERM SIGINT SIGHUP SIGQUIT
# Start the VM in the background
echo "Starting Ubuntu VM..."
/usr/bin/tini -s /run/entry.sh &
VM_PID=$!
echo "Live stream accessible at localhost:8006"
echo "Waiting for Ubuntu to boot and CUA computer-server to start..."
VM_IP=""
while true; do
# Wait for VM and get the IP
if [ -z "$VM_IP" ]; then
VM_IP=$(ps aux | grep dnsmasq | grep -oP '(?<=--dhcp-range=)[0-9.]+' | head -1)
if [ -n "$VM_IP" ]; then
echo "Detected VM IP: $VM_IP"
else
echo "Waiting for VM to start..."
sleep 5
continue
fi
fi
# Check if server is ready
response=$(curl --write-out '%{http_code}' --silent --output /dev/null $VM_IP:5000/status)
if [ "${response:-0}" -eq 200 ]; then
break
fi
echo "Waiting for CUA computer-server to be ready. This might take a while..."
sleep 5
done
echo "VM is up and running, and the CUA Computer Server is ready!"
echo "Computer server accessible at localhost:5000"
# Detect initial setup by presence of custom ISO
CUSTOM_ISO=$(find / -maxdepth 1 -type f -iname "*.iso" -print -quit 2>/dev/null || true)
if [ -n "$CUSTOM_ISO" ]; then
echo "Preparation complete. Shutting down gracefully..."
cleanup
fi
# Keep container alive for golden image boots
echo "Container running. Press Ctrl+C to stop."
tail -f /dev/null
```
--------------------------------------------------------------------------------
/docs/content/docs/agent-sdk/callbacks/agent-lifecycle.mdx:
--------------------------------------------------------------------------------
```markdown
---
title: Agent Lifecycle
description: Agent callback lifecycle and hooks
---
# Callbacks
Callbacks provide hooks into the agent lifecycle for extensibility. They're called in a specific order during agent execution.
## Callback Lifecycle
### 1. `on_run_start(kwargs, old_items)`
Called once when agent run begins. Initialize tracking, logging, or state.
### 2. `on_run_continue(kwargs, old_items, new_items)` → bool
Called before each iteration. Return `False` to stop execution (e.g., budget limits).
### 3. `on_llm_start(messages)` → messages
Preprocess messages before LLM call. Use for PII anonymization, image retention.
### 4. `on_api_start(kwargs)`
Called before each LLM API call.
### 5. `on_api_end(kwargs, result)`
Called after each LLM API call completes.
### 6. `on_usage(usage)`
Called when usage information is received from LLM.
### 7. `on_llm_end(messages)` → messages
Postprocess messages after LLM call. Use for PII deanonymization.
### 8. `on_responses(kwargs, responses)`
Called when responses are received from agent loop.
### 9. Response-specific hooks:
- `on_text(item)` - Text messages
- `on_computer_call_start(item)` - Before computer actions
- `on_computer_call_end(item, result)` - After computer actions
- `on_function_call_start(item)` - Before function calls
- `on_function_call_end(item, result)` - After function calls
- `on_screenshot(screenshot, name)` - When screenshots are taken
### 10. `on_run_end(kwargs, old_items, new_items)`
Called when agent run completes. Finalize tracking, save trajectories.
```
--------------------------------------------------------------------------------
/libs/python/bench-ui/examples/gui/styles.css:
--------------------------------------------------------------------------------
```css
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background: white;
border-radius: 12px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
max-width: 600px;
width: 100%;
}
h1 {
color: #333;
margin-top: 0;
font-size: 2em;
}
p {
color: #666;
line-height: 1.6;
}
.image-container {
display: flex;
justify-content: center;
margin: 30px 0;
}
.logo {
width: 150px;
height: 150px;
}
.info {
background: #f8f9fa;
border-left: 4px solid #667eea;
padding: 20px;
margin: 20px 0;
border-radius: 4px;
}
.info ul {
margin: 10px 0;
padding-left: 20px;
}
.info li {
color: #555;
margin: 8px 0;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 30px;
font-size: 16px;
border-radius: 6px;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
font-weight: 600;
}
.btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn:active:not(:disabled) {
transform: translateY(0);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
#status {
margin-top: 15px;
font-weight: 600;
color: #28a745;
font-size: 18px;
}
```
--------------------------------------------------------------------------------
/libs/python/computer-server/computer_server/diorama/macos.py:
--------------------------------------------------------------------------------
```python
import inspect
import platform
import sys
from typing import Optional
from computer_server.diorama.base import BaseDioramaHandler
from computer_server.diorama.diorama import Diorama
class MacOSDioramaHandler(BaseDioramaHandler):
"""Handler for Diorama commands on macOS, using local diorama module."""
async def diorama_cmd(self, action: str, arguments: Optional[dict] = None) -> dict:
if platform.system().lower() != "darwin":
return {"success": False, "error": "Diorama is only supported on macOS."}
try:
app_list = arguments.get("app_list") if arguments else None
if not app_list:
return {"success": False, "error": "Missing 'app_list' in arguments"}
diorama = Diorama(app_list)
interface = diorama.interface
if not hasattr(interface, action):
return {"success": False, "error": f"Unknown diorama action: {action}"}
method = getattr(interface, action)
# Remove app_list from arguments before calling the method
filtered_arguments = dict(arguments)
filtered_arguments.pop("app_list", None)
if inspect.iscoroutinefunction(method):
result = await method(**(filtered_arguments or {}))
else:
result = method(**(filtered_arguments or {}))
return {"success": True, "result": result}
except Exception as e:
import traceback
return {"success": False, "error": str(e), "trace": traceback.format_exc()}
```
--------------------------------------------------------------------------------
/docs/src/lib/source.ts:
--------------------------------------------------------------------------------
```typescript
import { docs } from '@/.source';
import { loader } from 'fumadocs-core/source';
import { icons } from 'lucide-react';
import { createElement } from 'react';
import fs from 'node:fs/promises';
import path from 'node:path';
/**
* Returns available API doc versions for a given section (e.g., 'agent').
* Each version is an object: { label, slug }
* - 'Current' (index.mdx) → slug: []
* - '[version].mdx' → slug: [version]
*/
export async function getApiVersions(
section: string
): Promise<{ label: string; slug: string[] }[]> {
const dir = path.join(process.cwd(), 'content/docs/api', section);
let files: string[] = [];
try {
files = (await fs.readdir(dir)).filter((f) => f.endsWith('.mdx'));
} catch (_e) {
return [];
}
const versions = files.map((file) => {
if (file === 'index.mdx') {
return { label: 'Current', slug: [] };
}
const version = file.replace(/\.mdx$/, '');
return { label: version, slug: [version] };
});
// Always put 'Current' first, then others sorted descending (semver-ish)
return [
...versions.filter((v) => v.label === 'Current'),
...versions
.filter((v) => v.label !== 'Current')
.sort((a, b) => b.label.localeCompare(a.label, undefined, { numeric: true })),
];
}
// See https://fumadocs.vercel.app/docs/headless/source-api for more info
export const source = loader({
// it assigns a URL to your pages
baseUrl: '/',
source: docs.toFumadocsSource(),
icon(icon) {
if (!icon) return;
if (icon in icons) return createElement(icons[icon as keyof typeof icons]);
},
});
```
--------------------------------------------------------------------------------
/libs/python/som/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project]
name = "cua-som"
version = "0.1.3"
description = "Computer Vision and OCR library for detecting and analyzing UI elements"
authors = [
{ name = "TryCua", email = "[email protected]" }
]
dependencies = [
"torch>=2.2.1",
"torchvision>=0.17.1",
"ultralytics>=8.1.28",
"easyocr>=1.7.1",
"numpy>=1.26.4",
"pillow>=10.2.0",
"setuptools>=75.8.1",
"opencv-python-headless>=4.11.0.86",
"matplotlib>=3.8.3",
"huggingface-hub>=0.21.4",
"supervision>=0.25.1",
"typing-extensions>=4.9.0",
"pydantic>=2.6.3"
]
requires-python = ">=3.12,<3.14"
readme = "README.md"
license = {text = "AGPL-3.0-or-later"}
keywords = ["computer-vision", "ocr", "ui-analysis", "icon-detection"]
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Scientific/Engineering :: Image Recognition"
]
[project.urls]
Homepage = "https://github.com/trycua/cua"
Repository = "https://github.com/trycua/cua"
Documentation = "https://github.com/trycua/cua/tree/main/docs"
[tool.pdm]
distribution = true
package-type = "library"
src-layout = false
[tool.pdm.build]
includes = ["som/"]
source-includes = ["tests/", "README.md", "LICENSE"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = "test_*.py"
```
--------------------------------------------------------------------------------
/libs/python/computer-server/computer_server/diorama/diorama_computer.py:
--------------------------------------------------------------------------------
```python
import asyncio
class DioramaComputer:
"""
A minimal Computer-like interface for Diorama, compatible with ComputerAgent.
Implements _initialized, run(), and __aenter__ for agent compatibility.
"""
def __init__(self, diorama):
"""
Initialize the DioramaComputer with a diorama instance.
Args:
diorama: The diorama instance to wrap with a computer-like interface.
"""
self.diorama = diorama
self.interface = self.diorama.interface
self._initialized = False
async def __aenter__(self):
"""
Async context manager entry method for compatibility with ComputerAgent.
Ensures an event loop is running and marks the instance as initialized.
Creates a new event loop if none is currently running.
Returns:
DioramaComputer: The initialized instance.
"""
# Ensure the event loop is running (for compatibility)
try:
asyncio.get_running_loop()
except RuntimeError:
asyncio.set_event_loop(asyncio.new_event_loop())
self._initialized = True
return self
async def run(self):
"""
Run method stub for compatibility with ComputerAgent interface.
Ensures the instance is initialized before returning. If not already
initialized, calls __aenter__ to perform initialization.
Returns:
DioramaComputer: The initialized instance.
"""
# This is a stub for compatibility
if not self._initialized:
await self.__aenter__()
return self
```
--------------------------------------------------------------------------------
/libs/lume/src/VM/VMDetails.swift:
--------------------------------------------------------------------------------
```swift
import Foundation
import Network
struct DiskSize: Codable {
let allocated: UInt64
let total: UInt64
}
extension DiskSize {
var formattedAllocated: String {
formatBytes(allocated)
}
var formattedTotal: String {
formatBytes(total)
}
private func formatBytes(_ bytes: UInt64) -> String {
let units = ["B", "KB", "MB", "GB", "TB"]
var size = Double(bytes)
var unitIndex = 0
while size >= 1024 && unitIndex < units.count - 1 {
size /= 1024
unitIndex += 1
}
return String(format: "%.1f%@", size, units[unitIndex])
}
}
struct VMDetails: Codable {
let name: String
let os: String
let cpuCount: Int
let memorySize: UInt64
let diskSize: DiskSize
let display: String
let status: String
let vncUrl: String?
let ipAddress: String?
let locationName: String
let sharedDirectories: [SharedDirectory]?
init(
name: String,
os: String,
cpuCount: Int,
memorySize: UInt64,
diskSize: DiskSize,
display: String,
status: String,
vncUrl: String?,
ipAddress: String?,
locationName: String,
sharedDirectories: [SharedDirectory]? = nil
) {
self.name = name
self.os = os
self.cpuCount = cpuCount
self.memorySize = memorySize
self.diskSize = diskSize
self.display = display
self.status = status
self.vncUrl = vncUrl
self.ipAddress = ipAddress
self.locationName = locationName
self.sharedDirectories = sharedDirectories
}
}
```
--------------------------------------------------------------------------------
/examples/sandboxed_functions_examples.py:
--------------------------------------------------------------------------------
```python
import os
import sys
from pathlib import Path
# Load environment variables from .env file
project_root = Path(__file__).parent.parent
env_file = project_root / ".env"
print(f"Loading environment from: {env_file}")
from dotenv import load_dotenv
load_dotenv(env_file)
# Add paths to sys.path if needed
pythonpath = os.environ.get("PYTHONPATH", "")
for path in pythonpath.split(":"):
if path and path not in sys.path:
sys.path.insert(0, path) # Insert at beginning to prioritize
print(f"Added to sys.path: {path}")
import asyncio
from computer.computer import Computer
from computer.helpers import sandboxed
async def main():
# Initialize the computer in a Cua Container
computer = Computer()
await computer.run()
# Install a package in a virtual environment in the container
await computer.venv_install("demo_venv", ["requests", "macos-pyxa"])
# Open Safari
await computer.interface.run_command("open -a Safari")
await asyncio.sleep(2)
# Define a sandboxed function
# This function will run inside the Cua Container
@sandboxed("demo_venv")
def greet_and_print(name):
# get .html of the current Safari tab
import PyXA
safari = PyXA.Application("Safari")
current_doc = safari.current_document
html = current_doc.source()
print(f"Hello from inside the container, {name}!")
print("Safari HTML length:", len(html))
return {"greeted": name, "safari_html_length": len(html), "safari_html_snippet": html[:200]}
# Call with args and kwargs
result = await greet_and_print("Cua")
print("Result from sandboxed function:", result)
if __name__ == "__main__":
asyncio.run(main())
```
--------------------------------------------------------------------------------
/libs/lumier/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
# Base image using Debian for arm64 architecture (optimized for Apple Silicon)
FROM debian:bullseye-slim AS lumier-base
# Set environment variables for Lume API server configuration
ENV LUME_API_HOST="host.docker.internal"
# Default VM configuration (can be overridden at runtime)
ENV VERSION="ghcr.io/trycua/macos-sequoia-vanilla:latest"
ENV RAM_SIZE="8192"
ENV CPU_CORES="4"
ENV DISK_SIZE="100"
ENV DISPLAY="1024x768"
ENV VM_NAME="lumier"
ENV HOST_SHARED_PATH=""
ENV LUMIER_DEBUG="0"
# Install necessary tools and noVNC dependencies
RUN apt-get update && \
apt-get install -y \
netcat-traditional \
curl \
sshpass \
wget \
unzip \
git \
python3 \
python3-pip \
python3-numpy \
procps && \
rm -rf /var/lib/apt/lists/*
# Download and install noVNC without caching
RUN wget https://github.com/trycua/noVNC/archive/refs/heads/master.zip -O master1.zip && \
unzip master1.zip && \
mv noVNC-master /opt/noVNC && \
rm master1.zip
# Set environment variables for noVNC
ENV NOVNC_PATH="/opt/noVNC"
# Create necessary directories
RUN mkdir -p /run/bin /run/lib /run/config /run/hooks /run/lifecycle
# Copy scripts to the container
COPY src/config/constants.sh /run/config/
COPY src/bin/entry.sh /run/bin/entry.sh
# Copy library files if they exist
COPY src/lib/ /run/lib/
COPY src/hooks/ /run/hooks/
# Copy on-logon script to lifecycle directory
COPY src/hooks/on-logon.sh /run/lifecycle/
# Make scripts executable
RUN chmod +x \
/run/bin/* \
/run/hooks/* \
/run/lifecycle/* 2>/dev/null || true
# Expose ports for noVNC and Lume API
EXPOSE 8006
# VOLUME setup
VOLUME [ "/storage" ]
VOLUME [ "/data" ]
# Default entrypoint
ENTRYPOINT ["/run/bin/entry.sh"]
```