mirror of
https://github.com/trycua/computer.git
synced 2026-01-01 11:00:31 -06:00
Lots of changes -- package & platform metadata, work on agent & computer page, add more guides
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: FAQ
|
||||
description: C/ua's frequently asked questions. Find answers to the most common issues or questions when using C/ua tools.
|
||||
description: Find answers to the most common issues or questions when using C/ua tools.
|
||||
icon: CircleQuestionMark
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "C/ua",
|
||||
"description": "C/ua",
|
||||
"icon": "House"
|
||||
"title": "Guides",
|
||||
"description": "Guides",
|
||||
"icon": "BookCopy"
|
||||
}
|
||||
@@ -11,20 +11,16 @@ C/ua is a collection of cross-platform libraries and tools for building Computer
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://docs.trycua.com/home/cua/computer-use-agent-quickstart"
|
||||
href="./home/guides/computer-use-agent-quickstart"
|
||||
title="Computer-Use Agent UI">
|
||||
Read our guide on getting started with a Computer-Use Agent.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
href="https://docs.trycua.com/home/cua/cua-usage-guide"
|
||||
title="C/ua Usage Guide">
|
||||
<Card href="./home/guides/cua-usage-guide" title="C/ua Usage Guide">
|
||||
Get started using C/ua services on your machine.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
href="https://docs.trycua.com/home/cua/dev-container-setup"
|
||||
title="Dev Container Setup">
|
||||
<Card href="./home/guides/dev-container-setup" title="Dev Container Setup">
|
||||
Set up a development environment with the Dev Container.
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
---
|
||||
title: Agent
|
||||
---
|
||||
|
||||
<div
|
||||
align="center"
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: '10px',
|
||||
margin: '0 auto',
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<a href="#">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Python-333333?logo=python&logoColor=white&labelColor=blue"
|
||||
alt="Python"
|
||||
/>
|
||||
</a>
|
||||
<a href="#">
|
||||
<img
|
||||
src="https://img.shields.io/badge/macOS-000000?logo=apple&logoColor=F0F0F0"
|
||||
alt="macOS"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discord.com/invite/mVnXXpdE85">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white"
|
||||
alt="Discord"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://pypi.org/project/cua-computer/">
|
||||
<img
|
||||
src="https://img.shields.io/pypi/v/cua-computer?color=blue"
|
||||
alt="PyPI"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div
|
||||
align="center"
|
||||
style={{
|
||||
display: 'flex',
|
||||
margin: '0 0',
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<a href="/api/computer">
|
||||
Reference
|
||||
</a>
|
||||
</div>
|
||||
|
||||
**cua-agent** is a general Computer-Use framework for running multi-app agentic workflows targeting macOS and Linux sandbox created with C/ua, supporting local (Ollama) and cloud model providers (OpenAI, Anthropic, Groq, DeepSeek, Qwen).
|
||||
|
||||
### Get started with Agent
|
||||
|
||||
<div align="center">
|
||||
<img src="/img/agent.png" />
|
||||
</div>
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
pip install "cua-agent[all]"
|
||||
|
||||
# or install specific loop providers
|
||||
pip install "cua-agent[openai]" # OpenAI Cua Loop
|
||||
pip install "cua-agent[anthropic]" # Anthropic Cua Loop
|
||||
pip install "cua-agent[uitars]" # UI-Tars support
|
||||
pip install "cua-agent[omni]" # Cua Loop based on OmniParser (includes Ollama for local models)
|
||||
pip install "cua-agent[ui]" # Gradio UI for the agent
|
||||
|
||||
# For local UI-TARS with MLX support, you need to manually install mlx-vlm:
|
||||
pip install "cua-agent[uitars-mlx]"
|
||||
pip install git+https://github.com/ddupont808/mlx-vlm.git@stable/fix/qwen2-position-id # PR: https://github.com/Blaizzy/mlx-vlm/pull/349
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
async with Computer() as macos_computer:
|
||||
# Create agent with loop and provider
|
||||
agent = ComputerAgent(
|
||||
computer=macos_computer,
|
||||
loop=AgentLoop.OPENAI,
|
||||
model=LLM(provider=LLMProvider.OPENAI)
|
||||
# or
|
||||
# loop=AgentLoop.ANTHROPIC,
|
||||
# model=LLM(provider=LLMProvider.ANTHROPIC)
|
||||
# or
|
||||
# loop=AgentLoop.OMNI,
|
||||
# model=LLM(provider=LLMProvider.OLLAMA, name="gemma3")
|
||||
# or
|
||||
# loop=AgentLoop.UITARS,
|
||||
# model=LLM(provider=LLMProvider.OAICOMPAT, name="ByteDance-Seed/UI-TARS-1.5-7B", provider_base_url="https://**************.us-east-1.aws.endpoints.huggingface.cloud/v1")
|
||||
)
|
||||
|
||||
tasks = [
|
||||
"Look for a repository named trycua/cua on GitHub.",
|
||||
"Check the open issues, open the most recent one and read it.",
|
||||
"Clone the repository in users/lume/projects if it doesn't exist yet.",
|
||||
"Open the repository with an app named Cursor (on the dock, black background and white cube icon).",
|
||||
"From Cursor, open Composer if not already open.",
|
||||
"Focus on the Composer text area, then write and submit a task to help resolve the GitHub issue.",
|
||||
]
|
||||
|
||||
for i, task in enumerate(tasks):
|
||||
print(f"\nExecuting task {i}/{len(tasks)}: {task}")
|
||||
async for result in agent.run(task):
|
||||
print(result)
|
||||
|
||||
print(f"\n✅ Task {i+1}/{len(tasks)} completed: {task}")
|
||||
```
|
||||
|
||||
Refer to these notebooks for step-by-step guides on how to use the Computer-Use Agent (CUA):
|
||||
|
||||
- [Agent Notebook](https://github.com/trycua/cua/tree/main/notebooks/agent_nb.ipynb) - Complete examples and workflows
|
||||
|
||||
## Using the Gradio UI
|
||||
|
||||
The agent includes a Gradio-based user interface for easier interaction.
|
||||
|
||||
<div align="center">
|
||||
<img src="/img/agent_gradio_ui.png" />
|
||||
</div>
|
||||
|
||||
To use it:
|
||||
|
||||
```bash
|
||||
# Install with Gradio support
|
||||
pip install "cua-agent[ui]"
|
||||
```
|
||||
|
||||
### Create a simple launcher script
|
||||
|
||||
```python
|
||||
# launch_ui.py
|
||||
from agent.ui.gradio.app import create_gradio_ui
|
||||
|
||||
app = create_gradio_ui()
|
||||
app.launch(share=False)
|
||||
```
|
||||
|
||||
### Setting up API Keys
|
||||
|
||||
For the Gradio UI to show available models, you need to set API keys as environment variables:
|
||||
|
||||
```bash
|
||||
# For OpenAI models
|
||||
export OPENAI_API_KEY=your_openai_key_here
|
||||
|
||||
# For Anthropic models
|
||||
export ANTHROPIC_API_KEY=your_anthropic_key_here
|
||||
|
||||
# Launch with both keys set
|
||||
OPENAI_API_KEY=your_key ANTHROPIC_API_KEY=your_key python launch_ui.py
|
||||
```
|
||||
|
||||
Without these environment variables, the UI will show "No models available" for the corresponding providers, but you can still use local models with the OMNI loop provider.
|
||||
|
||||
### Using Local Models
|
||||
|
||||
You can use local models with the OMNI loop provider by selecting "Custom model..." from the dropdown. The default provider URL is set to `http://localhost:1234/v1` which works with LM Studio.
|
||||
|
||||
If you're using a different local model server:
|
||||
|
||||
- vLLM: `http://localhost:8000/v1`
|
||||
- LocalAI: `http://localhost:8080/v1`
|
||||
- Ollama with OpenAI compat API: `http://localhost:11434/v1`
|
||||
|
||||
The Gradio UI provides:
|
||||
|
||||
- Selection of different agent loops (OpenAI, Anthropic, OMNI)
|
||||
- Model selection for each provider
|
||||
- Configuration of agent parameters
|
||||
- Chat interface for interacting with the agent
|
||||
|
||||
### Using UI-TARS
|
||||
|
||||
The UI-TARS models are available in two forms:
|
||||
|
||||
1. **MLX UI-TARS models** (Default): These models run locally using MLXVLM provider
|
||||
|
||||
- `mlx-community/UI-TARS-1.5-7B-4bit` (default) - 4-bit quantized version
|
||||
- `mlx-community/UI-TARS-1.5-7B-6bit` - 6-bit quantized version for higher quality
|
||||
|
||||
```python
|
||||
agent = ComputerAgent(
|
||||
computer=macos_computer,
|
||||
loop=AgentLoop.UITARS,
|
||||
model=LLM(provider=LLMProvider.MLXVLM, name="mlx-community/UI-TARS-1.5-7B-4bit")
|
||||
)
|
||||
```
|
||||
|
||||
2. **OpenAI-compatible UI-TARS**: For using the original ByteDance model
|
||||
|
||||
- If you want to use the original ByteDance UI-TARS model via an OpenAI-compatible API, follow the [deployment guide](https://github.com/bytedance/UI-TARS/blob/main/README_deploy.md)
|
||||
- This will give you a provider URL like `https://**************.us-east-1.aws.endpoints.huggingface.cloud/v1` which you can use in the code or Gradio UI:
|
||||
|
||||
```python
|
||||
agent = ComputerAgent(
|
||||
computer=macos_computer,
|
||||
loop=AgentLoop.UITARS,
|
||||
model=LLM(provider=LLMProvider.OAICOMPAT, name="tgi",
|
||||
provider_base_url="https://**************.us-east-1.aws.endpoints.huggingface.cloud/v1")
|
||||
)
|
||||
```
|
||||
|
||||
## Agent Loops
|
||||
|
||||
The `cua-agent` package provides three agent loops variations, based on different CUA models providers and techniques:
|
||||
|
||||
| Agent Loop | Supported Models | Description | Set-Of-Marks |
|
||||
| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :----------- |
|
||||
| `AgentLoop.OPENAI` | • `computer_use_preview` | Use OpenAI Operator CUA model | Not Required |
|
||||
| `AgentLoop.ANTHROPIC` | • `claude-3-5-sonnet-20240620`<br/>• `claude-3-7-sonnet-20250219` | Use Anthropic Computer-Use | Not Required |
|
||||
| `AgentLoop.UITARS` | • `mlx-community/UI-TARS-1.5-7B-4bit` (default)<br/>• `mlx-community/UI-TARS-1.5-7B-6bit`<br/>• `ByteDance-Seed/UI-TARS-1.5-7B` (via openAI-compatible endpoint) | Uses UI-TARS models with MLXVLM (default) or OAICOMPAT providers | Not Required |
|
||||
| `AgentLoop.OMNI` | • `claude-3-5-sonnet-20240620`<br/>• `claude-3-7-sonnet-20250219`<br/>• `gpt-4.5-preview`<br/>• `gpt-4o`<br/>• `gpt-4`<br/>• `phi4`<br/>• `phi4-mini`<br/>• `gemma3`<br/>• `...`<br/>• `Any Ollama or OpenAI-compatible model` | Use OmniParser for element pixel-detection (SoM) and any VLMs for UI Grounding and Reasoning | OmniParser |
|
||||
|
||||
## AgentResponse
|
||||
|
||||
The `AgentResponse` class represents the structured output returned after each agent turn. It contains the agent's response, reasoning, tool usage, and other metadata. The response format aligns with the new [OpenAI Agent SDK specification](https://platform.openai.com/docs/api-reference/responses) for better consistency across different agent loops.
|
||||
|
||||
```python
|
||||
async for result in agent.run(task):
|
||||
print("Response ID: ", result.get("id"))
|
||||
|
||||
# Print detailed usage information
|
||||
usage = result.get("usage")
|
||||
if usage:
|
||||
print("\nUsage Details:")
|
||||
print(f" Input Tokens: {usage.get('input_tokens')}")
|
||||
if "input_tokens_details" in usage:
|
||||
print(f" Input Tokens Details: {usage.get('input_tokens_details')}")
|
||||
print(f" Output Tokens: {usage.get('output_tokens')}")
|
||||
if "output_tokens_details" in usage:
|
||||
print(f" Output Tokens Details: {usage.get('output_tokens_details')}")
|
||||
print(f" Total Tokens: {usage.get('total_tokens')}")
|
||||
|
||||
print("Response Text: ", result.get("text"))
|
||||
|
||||
# Print tools information
|
||||
tools = result.get("tools")
|
||||
if tools:
|
||||
print("\nTools:")
|
||||
print(tools)
|
||||
|
||||
# Print reasoning and tool call outputs
|
||||
outputs = result.get("output", [])
|
||||
for output in outputs:
|
||||
output_type = output.get("type")
|
||||
if output_type == "reasoning":
|
||||
print("\nReasoning Output:")
|
||||
print(output)
|
||||
elif output_type == "computer_call":
|
||||
print("\nTool Call Output:")
|
||||
print(output)
|
||||
```
|
||||
|
||||
**Note on Settings Persistence:**
|
||||
|
||||
- The Gradio UI automatically saves your configuration (Agent Loop, Model Choice, Custom Base URL, Save Trajectory state, Recent Images count) to a file named `.gradio_settings.json` in the project's root directory when you successfully run a task.
|
||||
- This allows your preferences to persist between sessions.
|
||||
- API keys entered into the custom provider field are **not** saved in this file for security reasons. Manage API keys using environment variables (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) or a `.env` file.
|
||||
- It's recommended to add `.gradio_settings.json` to your `.gitignore` file.
|
||||
158
docs/content/docs/home/libraries/agent/agent-gradio-ui.mdx
Normal file
158
docs/content/docs/home/libraries/agent/agent-gradio-ui.mdx
Normal file
@@ -0,0 +1,158 @@
|
||||
---
|
||||
title: Gradio UI with the Python Agent
|
||||
description: The agent module includes a Gradio-based user interface for easier interaction with Computer-Use Agent workflows.
|
||||
---
|
||||
|
||||
The agent includes a Gradio-based user interface for easier interaction.
|
||||
|
||||
<div align="center">
|
||||
<img src="/img/agent_gradio_ui.png" />
|
||||
</div>
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
# Install with Gradio support
|
||||
pip install "cua-agent[ui]"
|
||||
```
|
||||
|
||||
## Create a simple launcher script
|
||||
|
||||
```python
|
||||
# launch_ui.py
|
||||
from agent.ui.gradio.app import create_gradio_ui
|
||||
|
||||
app = create_gradio_ui()
|
||||
app.launch(share=False)
|
||||
```
|
||||
|
||||
### Run the launcher
|
||||
|
||||
```bash
|
||||
python launch_ui.py
|
||||
```
|
||||
|
||||
This will start the Gradio interface on `http://localhost:7860`.
|
||||
|
||||
## Features
|
||||
|
||||
The Gradio UI provides:
|
||||
|
||||
- **Model Selection**: Choose between different AI models and providers
|
||||
- **Task Input**: Enter tasks for the agent to execute
|
||||
- **Real-time Output**: View the agent's actions and results as they happen
|
||||
- **Screenshot Display**: See visual feedback from the computer screen
|
||||
- **Settings Management**: Configure and save your preferred settings
|
||||
|
||||
## Supported Providers
|
||||
|
||||
1. **OpenAI**: GPT-4 and GPT-4 Vision models
|
||||
2. **Anthropic**: Claude models
|
||||
3. **Ollama**: Local models like Gemma3
|
||||
4. **UI-TARS**: Specialized UI understanding models
|
||||
|
||||
### Using UI-TARS
|
||||
|
||||
UI-TARS is a specialized model for UI understanding tasks. You have two options:
|
||||
|
||||
1. **Local MLX UI-TARS**: For running the model locally on Apple Silicon
|
||||
|
||||
```bash
|
||||
# Install MLX support
|
||||
pip install "cua-agent[uitars-mlx]"
|
||||
pip install git+https://github.com/ddupont808/mlx-vlm.git@stable/fix/qwen2-position-id
|
||||
```
|
||||
|
||||
Then select "UI-TARS (MLX)" in the Gradio interface.
|
||||
|
||||
2. **OpenAI-compatible UI-TARS**: For using the original ByteDance model
|
||||
|
||||
- If you want to use the original ByteDance UI-TARS model via an OpenAI-compatible API, follow the [deployment guide](https://github.com/bytedance/UI-TARS/blob/main/README_deploy.md)
|
||||
- This will give you a provider URL like `https://**************.us-east-1.aws.endpoints.huggingface.cloud/v1` which you can use in the code or Gradio UI:
|
||||
|
||||
```python
|
||||
agent = ComputerAgent(
|
||||
computer=macos_computer,
|
||||
loop=AgentLoop.UITARS,
|
||||
model=LLM(
|
||||
provider=LLMProvider.OAICOMPAT,
|
||||
name="ByteDance-Seed/UI-TARS-1.5-7B",
|
||||
provider_base_url="https://**************.us-east-1.aws.endpoints.huggingface.cloud/v1"
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Or in the Gradio UI, select "OpenAI Compatible" and enter:
|
||||
- Model Name: `ByteDance-Seed/UI-TARS-1.5-7B`
|
||||
- Base URL: Your deployment URL
|
||||
- API Key: Your API key (if required)
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Provider Settings
|
||||
|
||||
You can configure custom providers in the UI:
|
||||
|
||||
1. Select "OpenAI Compatible" from the provider dropdown
|
||||
2. Enter your custom model name, base URL, and API key
|
||||
3. The settings will be saved for future sessions
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Set API keys as environment variables for security:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="your-openai-key"
|
||||
export ANTHROPIC_API_KEY="your-anthropic-key"
|
||||
export GROQ_API_KEY="your-groq-key"
|
||||
export DEEPSEEK_API_KEY="your-deepseek-key"
|
||||
export QWEN_API_KEY="your-qwen-key"
|
||||
```
|
||||
|
||||
Or use a `.env` file:
|
||||
|
||||
```bash
|
||||
# .env
|
||||
OPENAI_API_KEY=your-openai-key
|
||||
ANTHROPIC_API_KEY=your-anthropic-key
|
||||
# ... other keys
|
||||
```
|
||||
|
||||
## Settings Persistence
|
||||
|
||||
The Gradio UI automatically saves your settings to `.gradio_settings.json` in your working directory. This includes:
|
||||
|
||||
- Selected provider and model
|
||||
- Custom provider configurations (URLs and model names)
|
||||
- Other UI preferences
|
||||
|
||||
**Note**: API keys entered into the custom provider field are **not** saved in this file for security reasons. Manage API keys using environment variables (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) or a `.env` file.
|
||||
|
||||
It's recommended to add `.gradio_settings.json` to your `.gitignore` file.
|
||||
|
||||
## Example Usage
|
||||
|
||||
Here's a complete example of using the Gradio UI with different providers:
|
||||
|
||||
```python
|
||||
# launch_ui_with_env.py
|
||||
from agent.ui.gradio.app import create_gradio_ui
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Create and launch the UI
|
||||
app = create_gradio_ui()
|
||||
app.launch(share=False, server_port=7860)
|
||||
```
|
||||
|
||||
Once launched, you can:
|
||||
|
||||
1. Select your preferred AI provider and model
|
||||
2. Enter a task like "Open a web browser and search for Python tutorials"
|
||||
3. Click "Run" to execute the task
|
||||
4. Watch the agent perform the actions in real-time
|
||||
5. View screenshots and logs of the execution
|
||||
|
||||
The UI makes it easy to experiment with different models and tasks without writing code for each interaction.
|
||||
257
docs/content/docs/home/libraries/agent/index.mdx
Normal file
257
docs/content/docs/home/libraries/agent/index.mdx
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
title: Agent
|
||||
description: The Computer-Use framework for running multi-app agentic workflows targeting macOS, Linux, and Windows sandboxes.
|
||||
pypi: cua-computer
|
||||
macos: true
|
||||
windows: true
|
||||
linux: true
|
||||
---
|
||||
|
||||
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
|
||||
**Agent** is a powerful Computer-Use framework that enables AI agents to interact with desktop applications and perform complex multi-step workflows across macOS, Linux, and Windows environments. Built on the C/ua platform, it supports both local models (via Ollama) and cloud providers (OpenAI, Anthropic, Groq, DeepSeek, Qwen).
|
||||
|
||||
## Installation
|
||||
|
||||
Install CUA Agent with pip. Choose the installation that matches your needs:
|
||||
|
||||
### All Providers (Recommended)
|
||||
|
||||
```bash
|
||||
# Install everything you need
|
||||
pip install "cua-agent[all]"
|
||||
```
|
||||
|
||||
### Selective Installation
|
||||
|
||||
```bash
|
||||
# OpenAI models (GPT-4, Computer Use Preview)
|
||||
pip install "cua-agent[openai]"
|
||||
|
||||
# Anthropic models (Claude 3.5 Sonnet)
|
||||
pip install "cua-agent[anthropic]"
|
||||
|
||||
# Local UI-TARS models
|
||||
pip install "cua-agent[uitars]"
|
||||
|
||||
# OmniParser + Ollama for local models
|
||||
pip install "cua-agent[omni]"
|
||||
|
||||
# Gradio web interface
|
||||
pip install "cua-agent[ui]"
|
||||
```
|
||||
|
||||
### Advanced: Local UI-TARS with MLX
|
||||
|
||||
```bash
|
||||
pip install "cua-agent[uitars-mlx]"
|
||||
pip install git+https://github.com/ddupont808/mlx-vlm.git@stable/fix/qwen2-position-id
|
||||
```
|
||||
|
||||
### Requirements
|
||||
|
||||
- Python 3.8+
|
||||
- macOS, Linux, or Windows
|
||||
- For cloud providers: API keys (OpenAI, Anthropic, etc.)
|
||||
- For local models: Sufficient RAM and compute resources
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Here's a simple example to get you started with CUA Agent:
|
||||
|
||||
```python
|
||||
from cua_agent import ComputerAgent, AgentLoop, LLM, LLMProvider
|
||||
from cua_computer import Computer
|
||||
|
||||
# Set your API key
|
||||
import os
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key-here"
|
||||
|
||||
async with Computer() as computer:
|
||||
# Create agent with OpenAI
|
||||
agent = ComputerAgent(
|
||||
computer=computer,
|
||||
loop=AgentLoop.OPENAI,
|
||||
model=LLM(provider=LLMProvider.OPENAI)
|
||||
)
|
||||
|
||||
# Run a simple task
|
||||
async for result in agent.run("Open a text editor and write 'Hello, World!'"):
|
||||
print(result.get("text"))
|
||||
```
|
||||
|
||||
### Multi-Step Workflow
|
||||
|
||||
```python
|
||||
async with Computer() as computer:
|
||||
# Create agent with your preferred provider
|
||||
agent = ComputerAgent(
|
||||
computer=computer,
|
||||
loop=AgentLoop.OPENAI, # or ANTHROPIC, OMNI, UITARS
|
||||
model=LLM(provider=LLMProvider.OPENAI)
|
||||
)
|
||||
|
||||
# Define complex workflow
|
||||
tasks = [
|
||||
"Look for a repository named trycua/cua on GitHub.",
|
||||
"Check the open issues, open the most recent one and read it.",
|
||||
"Clone the repository in users/lume/projects if it doesn't exist yet.",
|
||||
"Open the repository with an app named Cursor.",
|
||||
"From Cursor, open Composer and write a task to help resolve the GitHub issue.",
|
||||
]
|
||||
|
||||
# Execute tasks sequentially
|
||||
for i, task in enumerate(tasks):
|
||||
print(f"\nExecuting task {i+1}/{len(tasks)}: {task}")
|
||||
async for result in agent.run(task):
|
||||
print(result.get("text"))
|
||||
print(f"✅ Task {i+1} completed")
|
||||
```
|
||||
|
||||
### Alternative Model Providers
|
||||
|
||||
```python
|
||||
# Anthropic Claude
|
||||
agent = ComputerAgent(
|
||||
computer=computer,
|
||||
loop=AgentLoop.ANTHROPIC,
|
||||
model=LLM(provider=LLMProvider.ANTHROPIC)
|
||||
)
|
||||
|
||||
# Local Ollama model
|
||||
agent = ComputerAgent(
|
||||
computer=computer,
|
||||
loop=AgentLoop.OMNI,
|
||||
model=LLM(provider=LLMProvider.OLLAMA, name="gemma3")
|
||||
)
|
||||
|
||||
# UI-TARS model
|
||||
agent = ComputerAgent(
|
||||
computer=computer,
|
||||
loop=AgentLoop.UITARS,
|
||||
model=LLM(
|
||||
provider=LLMProvider.OAICOMPAT,
|
||||
name="ByteDance-Seed/UI-TARS-1.5-7B",
|
||||
provider_base_url="https://your-endpoint.com/v1"
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
## Agent Loops
|
||||
|
||||
The `cua-agent` package provides three agent loops variations, based on different CUA models providers and techniques:
|
||||
|
||||
| Agent Loop | Supported Models | Description | Set-Of-Marks |
|
||||
| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :----------- |
|
||||
| `AgentLoop.OPENAI` | • `computer_use_preview` | Use OpenAI Operator CUA model | Not Required |
|
||||
| `AgentLoop.ANTHROPIC` | • `claude-3-5-sonnet-20240620`<br/>• `claude-3-7-sonnet-20250219` | Use Anthropic Computer-Use | Not Required |
|
||||
| `AgentLoop.UITARS` | • `mlx-community/UI-TARS-1.5-7B-4bit` (default)<br/>• `mlx-community/UI-TARS-1.5-7B-6bit`<br/>• `ByteDance-Seed/UI-TARS-1.5-7B` (via openAI-compatible endpoint) | Uses UI-TARS models with MLXVLM (default) or OAICOMPAT providers | Not Required |
|
||||
| `AgentLoop.OMNI` | • `claude-3-5-sonnet-20240620`<br/>• `claude-3-7-sonnet-20250219`<br/>• `gpt-4.5-preview`<br/>• `gpt-4o`<br/>• `gpt-4`<br/>• `phi4`<br/>• `phi4-mini`<br/>• `gemma3`<br/>• `...`<br/>• `Any Ollama or OpenAI-compatible model` | Use OmniParser for element pixel-detection (SoM) and any VLMs for UI Grounding and Reasoning | OmniParser |
|
||||
|
||||
## Agent Response
|
||||
|
||||
The `AgentResponse` class represents the structured output returned after each agent turn. It contains the agent's response, reasoning, tool usage, and other metadata. The response format aligns with the new [OpenAI Agent SDK specification](https://platform.openai.com/docs/api-reference/responses) for better consistency across different agent loops.
|
||||
|
||||
```typescript
|
||||
interface AgentResponse {
|
||||
id: string;
|
||||
text: string;
|
||||
usage?: {
|
||||
input_tokens: number;
|
||||
input_tokens_details?: {
|
||||
text_tokens: number;
|
||||
image_tokens: number;
|
||||
};
|
||||
output_tokens: number;
|
||||
output_tokens_details?: {
|
||||
text_tokens: number;
|
||||
reasoning_tokens: number;
|
||||
};
|
||||
total_tokens: number;
|
||||
};
|
||||
tools?: Array<{
|
||||
name: string;
|
||||
description: string;
|
||||
}>;
|
||||
output?: Array<{
|
||||
type: 'reasoning' | 'computer_call';
|
||||
content?: string; // for reasoning type
|
||||
tool_name?: string; // for computer_call type
|
||||
parameters?: Record<string, any>; // for computer_call type
|
||||
result?: string; // for computer_call type
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
async for result in agent.run(task):
|
||||
print("Response ID: ", result.get("id"))
|
||||
|
||||
# Print detailed usage information
|
||||
usage = result.get("usage")
|
||||
if usage:
|
||||
print("\nUsage Details:")
|
||||
print(f" Input Tokens: {usage.get('input_tokens')}")
|
||||
if "input_tokens_details" in usage:
|
||||
print(f" Input Tokens Details: {usage.get('input_tokens_details')}")
|
||||
print(f" Output Tokens: {usage.get('output_tokens')}")
|
||||
if "output_tokens_details" in usage:
|
||||
print(f" Output Tokens Details: {usage.get('output_tokens_details')}")
|
||||
print(f" Total Tokens: {usage.get('total_tokens')}")
|
||||
|
||||
print("Response Text: ", result.get("text"))
|
||||
|
||||
# Print tools information
|
||||
tools = result.get("tools")
|
||||
if tools:
|
||||
print("\nTools:")
|
||||
print(tools)
|
||||
|
||||
# Print reasoning and tool call outputs
|
||||
outputs = result.get("output", [])
|
||||
for output in outputs:
|
||||
output_type = output.get("type")
|
||||
if output_type == "reasoning":
|
||||
print("\nReasoning Output:")
|
||||
print(output)
|
||||
elif output_type == "computer_call":
|
||||
print("\nTool Call Output:")
|
||||
print(output)
|
||||
```
|
||||
|
||||
## Examples & Guides
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://github.com/trycua/cua/tree/main/notebooks/agent_nb.ipynb"
|
||||
title="Agent Notebook">
|
||||
Step-by-step instructions on using the Computer-Use Agent (CUA)
|
||||
</Card>
|
||||
<Card href="../libraries/agent/agent-gradio-ui" title="Agent Gradio Guide">
|
||||
Use the Agent library with a Python Gradio UI
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
---
|
||||
|
||||
<Callout type="info">
|
||||
**Need detailed API documentation?** Explore the complete API reference with
|
||||
detailed class documentation, and method signatures.
|
||||
<a
|
||||
href="/api/agent"
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'secondary',
|
||||
}),
|
||||
'no-underline h-10'
|
||||
)}>
|
||||
View API Reference
|
||||
<ChevronRight />
|
||||
</a>
|
||||
</Callout>
|
||||
@@ -1,275 +0,0 @@
|
||||
---
|
||||
title: Computer
|
||||
---
|
||||
|
||||
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<div
|
||||
align="center"
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: '10px',
|
||||
margin: '0 auto',
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<a href="#">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Python-333333?logo=python&logoColor=white&labelColor=blue"
|
||||
alt="Python"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://pypi.org/project/cua-computer/">
|
||||
<img
|
||||
src="https://img.shields.io/pypi/v/cua-computer?color=blue"
|
||||
alt="PyPI"
|
||||
/>
|
||||
</a>
|
||||
<a href="#">
|
||||
<img
|
||||
src="https://img.shields.io/badge/TypeScript-333333?logo=typescript&logoColor=white&labelColor=3178C6"
|
||||
alt="TypeScript"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/@cua/computer">
|
||||
<img
|
||||
alt="NPM Version"
|
||||
src="https://img.shields.io/npm/v/react?color=CB3837"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
align="center"
|
||||
style={{
|
||||
display: 'flex',
|
||||
margin: '0 0',
|
||||
width: '100%',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<a href="/api/computer">
|
||||
Reference
|
||||
</a>
|
||||
</div>
|
||||
|
||||
**cua-computer** is a Computer-Use Interface (CUI) framework powering Cua for interacting with local macOS and Linux sandboxes. It's PyAutoGUI-compatible and pluggable with any AI agent systems (Cua, Langchain, CrewAI, AutoGen). Computer relies on [Lume](./lume.mdx) for creating and managing sandbox environments.
|
||||
|
||||
<div align="center">
|
||||
<img src="/img/computer.png" />
|
||||
</div>
|
||||
|
||||
## Key Features
|
||||
|
||||
- Create and manage virtual machine sandboxes
|
||||
- Take screenshots of the virtual machine
|
||||
- Control mouse movements and clicks
|
||||
- Simulate keyboard input
|
||||
- Manage clipboard content
|
||||
- Interact with the operating system interface
|
||||
- Support for macOS and Linux environments
|
||||
|
||||
## Installation
|
||||
|
||||
<Tabs groupId='language' persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
|
||||
To install the Computer-Use Interface (CUI) for Python:
|
||||
|
||||
```bash
|
||||
pip install "cua-computer[all]"
|
||||
```
|
||||
|
||||
The `cua-computer` PyPi package pulls automatically the latest executable version of Lume through [pylume](https://github.com/trycua/pylume).
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
To install the Computer-Use Interface (CUI) for TypeScript:
|
||||
```bash
|
||||
npm install @cua/computer
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Tabs groupId='language' persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
```python
|
||||
from computer import Computer
|
||||
|
||||
computer = Computer(os_type="macos", display="1024x768", memory="8GB", cpu="4")
|
||||
try:
|
||||
await computer.run()
|
||||
|
||||
screenshot = await computer.interface.screenshot()
|
||||
with open("screenshot.png", "wb") as f:
|
||||
f.write(screenshot)
|
||||
|
||||
await computer.interface.move_cursor(100, 100)
|
||||
await computer.interface.left_click()
|
||||
await computer.interface.right_click(300, 300)
|
||||
await computer.interface.double_click(400, 400)
|
||||
|
||||
await computer.interface.type("Hello, World!")
|
||||
await computer.interface.press_key("enter")
|
||||
|
||||
await computer.interface.set_clipboard("Test clipboard")
|
||||
content = await computer.interface.copy_to_clipboard()
|
||||
print(f"Clipboard content: {content}")
|
||||
finally:
|
||||
await computer.stop()
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
```typescript
|
||||
import { Computer, OSType } from '@cua/computer';
|
||||
|
||||
const main = async () => {
|
||||
// Create a cloud-based computer
|
||||
const computer = new Computer({
|
||||
name: 'cloud-vm',
|
||||
osType: OSType.Linux,
|
||||
apiKey: 'your-api-key',
|
||||
});
|
||||
|
||||
// Access the interface
|
||||
const interface = computer.interface;
|
||||
|
||||
// Screenshot operations
|
||||
const screenshot = await interface.screenshot();
|
||||
|
||||
// Mouse operations
|
||||
await interface.moveCursor(100, 100);
|
||||
await interface.leftClick();
|
||||
await interface.rightClick(300, 300);
|
||||
await interface.doubleClick(400, 400);
|
||||
await interface.dragTo(500, 500, 'left', 1000); // Drag with left button for 1 second
|
||||
|
||||
// Keyboard operations
|
||||
await interface.typeText('Hello from TypeScript!');
|
||||
await interface.pressKey('enter');
|
||||
await interface.hotkey('command', 'a'); // Select all
|
||||
|
||||
// Clipboard operations
|
||||
await interface.setClipboard('Clipboard content');
|
||||
const content = await interface.copyToClipboard();
|
||||
|
||||
// File operations
|
||||
await interface.writeText('/tmp/test.txt', 'Hello world');
|
||||
const fileContent = await interface.readText('/tmp/test.txt');
|
||||
|
||||
// Run a command in the VM
|
||||
const [stdout, stderr] = await interface.runCommand('ls -la');
|
||||
|
||||
// Disconnect from the cloud VM
|
||||
await computer.disconnect();
|
||||
};
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Getting Started
|
||||
|
||||
<Tabs groupId='language' persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
Refer to this notebook for a step-by-step guide on how to use the Computer-Use Interface (CUI):
|
||||
|
||||
- [Computer-Use Interface (CUI)](https://github.com/trycua/cua/tree/main/notebooks/samples/computer_nb.ipynb)
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
Check out the examples in the repository for more detailed usage patterns and advanced scenarios.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Using the Gradio Computer UI (Python Only)
|
||||
|
||||
The computer module includes a Gradio UI for creating and sharing demonstration data. We make it easy for people to build community datasets for better computer use models with an upload to Huggingface feature.
|
||||
|
||||
```bash
|
||||
# Install with UI support
|
||||
pip install "cua/computer[ui]"
|
||||
```
|
||||
|
||||
> **Note:** For precise control of the computer, we recommend using VNC or Screen Sharing instead of the Computer Gradio UI.
|
||||
|
||||
### Building and Sharing Demonstrations with Huggingface
|
||||
|
||||
Follow these steps to contribute your own demonstrations:
|
||||
|
||||
#### 1. Set up Huggingface Access
|
||||
|
||||
Set your HF_TOKEN in a .env file or in your environment variables:
|
||||
|
||||
```bash
|
||||
# In .env file
|
||||
HF_TOKEN=your_huggingface_token
|
||||
```
|
||||
|
||||
#### 2. Launch the Computer UI
|
||||
|
||||
```python
|
||||
# launch_ui.py
|
||||
from computer.ui.gradio.app import create_gradio_ui
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv('.env')
|
||||
|
||||
app = create_gradio_ui()
|
||||
app.launch(share=False)
|
||||
```
|
||||
|
||||
For examples, see [Computer UI Examples](https://github.com/trycua/cua/tree/main/examples/computer_ui_examples.py)
|
||||
|
||||
#### 3. Record Your Tasks
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/de3c3477-62fe-413c-998d-4063e48de176"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Record yourself performing various computer tasks using the UI.
|
||||
|
||||
#### 4. Save Your Demonstrations
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/5ad1df37-026a-457f-8b49-922ae805faef"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Save each task by picking a descriptive name and adding relevant tags (e.g., "office", "web-browsing", "coding").
|
||||
|
||||
#### 5. Record Additional Demonstrations
|
||||
|
||||
Repeat steps 3 and 4 until you have a good amount of demonstrations covering different tasks and scenarios.
|
||||
|
||||
#### 6. Upload to Huggingface
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/c586d460-3877-4b5f-a736-3248886d2134"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Upload your dataset to Huggingface by:
|
||||
|
||||
- Naming it as `{your_username}/{dataset_name}`
|
||||
- Choosing public or private visibility
|
||||
- Optionally selecting specific tags to upload only tasks with certain tags
|
||||
|
||||
#### Examples and Resources
|
||||
|
||||
- Example Dataset: [ddupont/test-dataset](https://huggingface.co/datasets/ddupont/test-dataset)
|
||||
- Find Community Datasets: 🔍 [Browse CUA Datasets on Huggingface](https://huggingface.co/datasets?other=cua)
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Gradio UI with the Python Computer Interface
|
||||
description: The computer module includes a Gradio UI for creating and sharing demonstration data. This guide makes it easy for people to build community datasets for better computer use models with an upload to Huggingface feature.
|
||||
---
|
||||
|
||||
<Callout title="Note">
|
||||
For precise control of the computer, we recommend using VNC or Screen Sharing
|
||||
instead of Gradio UI.
|
||||
</Callout>
|
||||
|
||||
```bash
|
||||
# Install with UI support
|
||||
pip install "cua/computer[ui]"
|
||||
```
|
||||
|
||||
## Building and Sharing Demonstrations with Huggingface
|
||||
|
||||
Follow these steps to contribute your own demonstrations:
|
||||
|
||||
### 1. Set up Huggingface Access
|
||||
|
||||
Set your HF_TOKEN in a .env file or in your environment variables:
|
||||
|
||||
```bash
|
||||
# In .env file
|
||||
HF_TOKEN=your_huggingface_token
|
||||
```
|
||||
|
||||
### 2. Launch the Computer UI
|
||||
|
||||
```python
|
||||
# launch_ui.py
|
||||
from computer.ui.gradio.app import create_gradio_ui
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv('.env')
|
||||
|
||||
app = create_gradio_ui()
|
||||
app.launch(share=False)
|
||||
```
|
||||
|
||||
For examples, see [Computer UI Examples](https://github.com/trycua/cua/tree/main/examples/computer_ui_examples.py)
|
||||
|
||||
### 3. Record Your Tasks
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/de3c3477-62fe-413c-998d-4063e48de176"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Record yourself performing various computer tasks using the UI.
|
||||
|
||||
### 4. Save Your Demonstrations
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/5ad1df37-026a-457f-8b49-922ae805faef"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Save each task by picking a descriptive name and adding relevant tags (e.g., "office", "web-browsing", "coding").
|
||||
|
||||
### 5. Record Additional Demonstrations
|
||||
|
||||
Repeat steps 3 and 4 until you have a good amount of demonstrations covering different tasks and scenarios.
|
||||
|
||||
### 6. Upload to Huggingface
|
||||
|
||||
<details open>
|
||||
<summary>View demonstration video</summary>
|
||||
<video
|
||||
src="https://github.com/user-attachments/assets/c586d460-3877-4b5f-a736-3248886d2134"
|
||||
controls
|
||||
width="600"></video>
|
||||
</details>
|
||||
|
||||
Upload your dataset to Huggingface by:
|
||||
|
||||
- Naming it as `{your_username}/{dataset_name}`
|
||||
- Choosing public or private visibility
|
||||
- Optionally selecting specific tags to upload only tasks with certain tags
|
||||
|
||||
### Examples and Resources
|
||||
|
||||
- Example Dataset: [ddupont/test-dataset](https://huggingface.co/datasets/ddupont/test-dataset)
|
||||
- Find Community Datasets: 🔍 [Browse CUA Datasets on Huggingface](https://huggingface.co/datasets?other=cua)
|
||||
177
docs/content/docs/home/libraries/computer/index.mdx
Normal file
177
docs/content/docs/home/libraries/computer/index.mdx
Normal file
@@ -0,0 +1,177 @@
|
||||
---
|
||||
title: Computer
|
||||
description: The Computer-Use Interface (CUI) framework for interacting with local macOS, Linux, and Windows sandboxes.
|
||||
macos: true
|
||||
windows: true
|
||||
linux: true
|
||||
pypi: cua-computer
|
||||
npm: '@trycua/computer'
|
||||
---
|
||||
|
||||
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
||||
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
|
||||
Computer powers Cua systems and is PyAutoGUI-compatible and pluggable with any AI agent system (Cua, Langchain, CrewAI, AutoGen). It relies on [Lume](./lume.mdx) for creating and managing sandbox environments.
|
||||
|
||||
## Installation
|
||||
|
||||
<Tabs groupId='language' persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
```bash
|
||||
pip install "cua-computer[all]"
|
||||
```
|
||||
The `cua-computer` PyPi package automatically pulls the latest executable version of Lume through [pylume](https://github.com/trycua/pylume).
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
```bash
|
||||
npm install @trycua/computer
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Key Features
|
||||
|
||||
- Create and manage virtual machine sandboxes
|
||||
- Take screenshots of the virtual machine
|
||||
- Control mouse movements and clicks
|
||||
- Simulate keyboard input
|
||||
- Manage clipboard content
|
||||
- Interact with the operating system interface
|
||||
- Support for macOS and Linux environments
|
||||
|
||||
## Simple Example
|
||||
|
||||
<Tabs groupId='language' persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
```python
|
||||
from computer import Computer
|
||||
|
||||
computer = Computer(os_type="macos", display="1024x768", memory="8GB", cpu="4")
|
||||
try:
|
||||
# Start a new local vm instance using Lume
|
||||
await computer.run()
|
||||
|
||||
# Interface with the instance
|
||||
screenshot = await computer.interface.screenshot()
|
||||
with open("screenshot.png", "wb") as f:
|
||||
f.write(screenshot)
|
||||
|
||||
await computer.interface.move_cursor(100, 100)
|
||||
await computer.interface.left_click()
|
||||
await computer.interface.right_click(300, 300)
|
||||
await computer.interface.double_click(400, 400)
|
||||
|
||||
await computer.interface.type("Hello, World!")
|
||||
await computer.interface.press_key("enter")
|
||||
|
||||
await computer.interface.set_clipboard("Test clipboard")
|
||||
content = await computer.interface.copy_to_clipboard()
|
||||
print(f"Clipboard content: {content}")
|
||||
finally:
|
||||
# Stop the vm instance
|
||||
await computer.stop()
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
```typescript
|
||||
import { Computer, OSType } from '@trycua/computer';
|
||||
|
||||
// This creates and interfaces with a cloud-based c/ua container.
|
||||
const main = async () => {
|
||||
// Create a cloud-based computer
|
||||
const computer = new Computer({
|
||||
name: 'cloud-vm',
|
||||
osType: OSType.Linux,
|
||||
apiKey: 'your-api-key',
|
||||
});
|
||||
|
||||
// Access the interface
|
||||
const interface = computer.interface;
|
||||
|
||||
// Screenshot operations
|
||||
const screenshot = await interface.screenshot();
|
||||
|
||||
// Mouse operations
|
||||
await interface.moveCursor(100, 100);
|
||||
await interface.leftClick();
|
||||
await interface.rightClick(300, 300);
|
||||
await interface.doubleClick(400, 400);
|
||||
await interface.dragTo(500, 500, 'left', 1000); // Drag with left button for 1 second
|
||||
|
||||
// Keyboard operations
|
||||
await interface.typeText('Hello from TypeScript!');
|
||||
await interface.pressKey('enter');
|
||||
await interface.hotkey('command', 'a'); // Select all
|
||||
|
||||
// Clipboard operations
|
||||
await interface.setClipboard('Clipboard content');
|
||||
const content = await interface.copyToClipboard();
|
||||
|
||||
// File operations
|
||||
await interface.writeText('/tmp/test.txt', 'Hello world');
|
||||
const fileContent = await interface.readText('/tmp/test.txt');
|
||||
|
||||
// Run a command in the VM
|
||||
const [stdout, stderr] = await interface.runCommand('ls -la');
|
||||
|
||||
// Disconnect from the cloud VM
|
||||
await computer.disconnect();
|
||||
};
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Examples & Guides
|
||||
|
||||
<Tabs groupId="language" persist items={['Python', 'TypeScript']}>
|
||||
<Tab value="Python">
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://github.com/trycua/cua/tree/main/notebooks/samples/computer_nb.ipynb"
|
||||
title="Computer-Use Interface (CUI)">
|
||||
Step-by-step guide on using the Computer-Use Interface (CUI)
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
href="../libraries/computer/computer-use-gradio-ui"
|
||||
title="Computer-Use Gradio UI">
|
||||
Use the Computer library with a Python Gradio UI
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
</Tab>
|
||||
<Tab value="TypeScript">
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://github.com/trycua/cua/tree/main/examples/computer-example-ts"
|
||||
title="Computer Cloud OpenAI">
|
||||
Use C/ua Cloud Containers with OpenAI's API to execute tasks in a sandbox
|
||||
</Card>
|
||||
</Cards>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
<Callout type="info">
|
||||
**Need detailed API documentation?** Explore the complete API reference with
|
||||
detailed class documentation, and method signatures.
|
||||
<a
|
||||
href="/api/computer"
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'secondary',
|
||||
}),
|
||||
'no-underline h-10'
|
||||
)}>
|
||||
View API Reference
|
||||
<ChevronRight />
|
||||
</a>
|
||||
</Callout>
|
||||
@@ -9,7 +9,12 @@
|
||||
"faq",
|
||||
"telemetry",
|
||||
"---[BookCopy]Guides---",
|
||||
"...guides",
|
||||
"guides/cua-usage-guide",
|
||||
"guides/developer-guide",
|
||||
"guides/dev-container-setup",
|
||||
"guides/computer-use-agent-quickstart",
|
||||
"guides/agent-gradio-ui",
|
||||
"guides/computer-use-gradio-ui",
|
||||
"---[Library]Libraries---",
|
||||
"...libraries"
|
||||
]
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
"lucide-react": "^0.525.0",
|
||||
"next": "15.3.3",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
"react-dom": "^19.1.0",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"zod": "^3.25.76"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
|
||||
14
docs/pnpm-lock.yaml
generated
14
docs/pnpm-lock.yaml
generated
@@ -29,6 +29,12 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.1.0
|
||||
version: 19.1.0(react@19.1.0)
|
||||
tailwind-merge:
|
||||
specifier: ^3.3.1
|
||||
version: 3.3.1
|
||||
zod:
|
||||
specifier: ^3.25.76
|
||||
version: 3.25.76
|
||||
devDependencies:
|
||||
'@biomejs/biome':
|
||||
specifier: 1.9.4
|
||||
@@ -1894,8 +1900,8 @@ packages:
|
||||
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
zod@3.25.67:
|
||||
resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==}
|
||||
zod@3.25.76:
|
||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||
|
||||
zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
@@ -2959,7 +2965,7 @@ snapshots:
|
||||
tinyexec: 1.0.1
|
||||
tinyglobby: 0.2.14
|
||||
unist-util-visit: 5.0.0
|
||||
zod: 3.25.67
|
||||
zod: 3.25.76
|
||||
transitivePeerDependencies:
|
||||
- acorn
|
||||
- supports-color
|
||||
@@ -4010,6 +4016,6 @@ snapshots:
|
||||
|
||||
yallist@5.0.0: {}
|
||||
|
||||
zod@3.25.67: {}
|
||||
zod@3.25.76: {}
|
||||
|
||||
zwitch@2.0.4: {}
|
||||
|
||||
@@ -4,12 +4,19 @@ import {
|
||||
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,
|
||||
schema: frontmatterSchema.extend({
|
||||
pypi: z.string().optional(),
|
||||
npm: z.string().optional(),
|
||||
macos: z.boolean().default(false),
|
||||
windows: z.boolean().default(false),
|
||||
linux: z.boolean().default(false),
|
||||
}),
|
||||
},
|
||||
meta: {
|
||||
schema: metaSchema,
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { notFound, redirect } from 'next/navigation';
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
@@ -24,9 +24,9 @@ export default async function Page(props: {
|
||||
const params = await props.params;
|
||||
const slug = params.slug || [];
|
||||
const page = source.getPage(slug);
|
||||
if (!page) notFound();
|
||||
if (!page) redirect('/home');
|
||||
|
||||
// Detect if this is an API reference page: /docs/api/[section] or /docs/api/[section]/[version]
|
||||
// Detect if this is an API reference page: /api/[section] or /api/[section]/[version]
|
||||
let apiSection: string | null = null;
|
||||
let apiVersionSlug: string[] = [];
|
||||
if (slug[0] === 'api' && slug.length >= 2) {
|
||||
@@ -41,72 +41,161 @@ export default async function Page(props: {
|
||||
versionItems = await getApiVersions(apiSection);
|
||||
}
|
||||
|
||||
const macos = page.data.macos;
|
||||
const windows = page.data.windows;
|
||||
const linux = page.data.linux;
|
||||
const pypi = page.data.pypi;
|
||||
const npm = page.data.npm;
|
||||
|
||||
const MDXContent = page.data.body;
|
||||
|
||||
// Platform icons component
|
||||
const PlatformIcons = () => {
|
||||
const hasAnyPlatform = macos || windows || linux;
|
||||
if (!hasAnyPlatform && !pypi) return null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 mx-4">
|
||||
{hasAnyPlatform && (
|
||||
<div className="flex flex-row gap-2 items-center mx-2 h-5 dark:text-neutral-400">
|
||||
{windows && (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 448 512">
|
||||
<title>Windows</title>
|
||||
<path d="M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z" />
|
||||
</svg>
|
||||
)}
|
||||
{macos && (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 384 512">
|
||||
<title>macOS</title>
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z" />
|
||||
</svg>
|
||||
)}
|
||||
{linux && (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 448 512">
|
||||
<title>Linux</title>
|
||||
<path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5 .2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4 .2-.8 .7-.6 1.1 .3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6 .2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5 .1-1.3 .6-3.4 1.5-3.2 2.9 .1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7 .1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9 .6 7.9 1.2 11.8 1.2 8.1 2.5 15.7 .8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1 .6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3 .4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4 .7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6 .6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7 .8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4 .6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1 .8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7 .4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6 .8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1 .3-.2 .7-.3 1-.5 .8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{pypi && (
|
||||
<a target="_blank" href={`https://pypi.org/project/${pypi}/`}>
|
||||
<img
|
||||
src={`https://img.shields.io/pypi/v/${pypi}?color=blue`}
|
||||
className="h-5"
|
||||
alt="PyPI"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
{npm && (
|
||||
<a target="_blank" href={`https://www.npmjs.com/package/${npm}`}>
|
||||
<img
|
||||
src={`https://img.shields.io/npm/v/${npm}?color=bf4c4b`}
|
||||
className="h-5"
|
||||
alt="NPM"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
{slug.includes('libraries') && (
|
||||
<a
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'secondary',
|
||||
size: 'sm',
|
||||
className:
|
||||
'gap-2 [&_svg]:size-3.5 [&_svg]:text-fd-muted-foreground',
|
||||
}),
|
||||
''
|
||||
)}
|
||||
href={`/api/${page.data.title.toLowerCase()}`}>
|
||||
Reference
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<div className="flex flex-row w-full">
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<div className="ml-auto">
|
||||
{apiSection && versionItems.length > 1 && (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'secondary',
|
||||
size: 'sm',
|
||||
className: 'gap-2',
|
||||
})
|
||||
)}>
|
||||
{(() => {
|
||||
// Find the current version label
|
||||
let currentLabel = 'Current';
|
||||
if (apiVersionSlug.length > 0) {
|
||||
const found = versionItems.find(
|
||||
(item) =>
|
||||
item.label !== 'Current' &&
|
||||
apiVersionSlug[0] === item.label
|
||||
);
|
||||
if (found) currentLabel = found.label;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
API Version: {currentLabel}
|
||||
<ChevronDown className="size-3.5 text-fd-muted-foreground" />
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col overflow-auto">
|
||||
{versionItems.map((item) => {
|
||||
// Build the href for each version
|
||||
const href =
|
||||
item.label === 'Current'
|
||||
? `/api/${apiSection}`
|
||||
: `/api/${apiSection}/${item.label}`;
|
||||
// Highlight current version
|
||||
const isCurrent =
|
||||
(item.label === 'Current' && apiVersionSlug.length === 0) ||
|
||||
(item.label !== 'Current' &&
|
||||
apiVersionSlug[0] === item.label);
|
||||
return (
|
||||
<Link
|
||||
key={item.label}
|
||||
href={href}
|
||||
className={cn(
|
||||
'px-3 py-1 rounded hover:bg-fd-muted',
|
||||
isCurrent && 'font-bold bg-fd-muted'
|
||||
)}>
|
||||
API version: {item.label}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
<div className="flex flex-row w-full items-start">
|
||||
<div className="flex-1">
|
||||
<div className="flex flex-row w-full">
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<div className="ml-auto">
|
||||
{apiSection && versionItems.length > 1 && (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: 'secondary',
|
||||
size: 'sm',
|
||||
className: 'gap-2',
|
||||
})
|
||||
)}>
|
||||
{(() => {
|
||||
// Find the current version label
|
||||
let currentLabel = 'Current';
|
||||
if (apiVersionSlug.length > 0) {
|
||||
const found = versionItems.find(
|
||||
(item) =>
|
||||
item.label !== 'Current' &&
|
||||
apiVersionSlug[0] === item.label
|
||||
);
|
||||
if (found) currentLabel = found.label;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
API Version: {currentLabel}
|
||||
<ChevronDown className="size-3.5 text-fd-muted-foreground" />
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col overflow-auto">
|
||||
{versionItems.map((item) => {
|
||||
// Build the href for each version
|
||||
const href =
|
||||
item.label === 'Current'
|
||||
? `/api/${apiSection}`
|
||||
: `/api/${apiSection}/${item.label}`;
|
||||
// Highlight current version
|
||||
const isCurrent =
|
||||
(item.label === 'Current' &&
|
||||
apiVersionSlug.length === 0) ||
|
||||
(item.label !== 'Current' &&
|
||||
apiVersionSlug[0] === item.label);
|
||||
return (
|
||||
<Link
|
||||
key={item.label}
|
||||
href={href}
|
||||
className={cn(
|
||||
'px-3 py-1 rounded hover:bg-fd-muted',
|
||||
isCurrent && 'font-bold bg-fd-muted'
|
||||
)}>
|
||||
API version: {item.label}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<DocsDescription className=" text-md mt-1">
|
||||
{page.data.description}
|
||||
</DocsDescription>
|
||||
</div>
|
||||
<PlatformIcons />
|
||||
</div>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDXContent
|
||||
components={getMDXComponents({
|
||||
@@ -130,8 +219,10 @@ export async function generateMetadata(props: {
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
let title = `c/ua Docs: ${page.data.title}`;
|
||||
if (page.url.includes('api')) title = `c/ua API: ${page.data.title}`;
|
||||
let title = `${page.data.title} | C/ua Docs`;
|
||||
if (page.url.includes('api')) title = `${page.data.title} | C/ua API Docs`;
|
||||
if (page.url.includes('guide'))
|
||||
title = ` Guide: ${page.data.title} | C/ua Docs`;
|
||||
|
||||
return {
|
||||
title,
|
||||
|
||||
Reference in New Issue
Block a user