From ae736be73fac6ed0fce139699f9a7a09182d7c48 Mon Sep 17 00:00:00 2001 From: f-trycua Date: Sun, 25 Jan 2026 12:31:43 -0800 Subject: [PATCH 1/3] feat(tools): add computer tool for GUI automation via cua-computer-server Add a new `computer` tool that enables agents to control desktop GUIs: - Take screenshots - Click, double-click, right-click at coordinates - Type text, press keys, hotkey combinations - Scroll in any direction - Move cursor, drag operations - Get screen size and cursor position Integrates with cua-computer-server which can run in: - Sandbox mode (cua-xfce, cua-ubuntu Docker images) - Node mode (Linux with supervisor setup) Includes setup documentation and example screenshot. --- docs/guides/computer-server-setup.md | 176 ++++++++++++ docs/guides/cua-xfce-screenshot.png | Bin 0 -> 83345 bytes src/agents/clawdbot-tools.ts | 7 + src/agents/tools/computer-server-client.ts | 227 +++++++++++++++ src/agents/tools/computer-tool.ts | 312 +++++++++++++++++++++ 5 files changed, 722 insertions(+) create mode 100644 docs/guides/computer-server-setup.md create mode 100644 docs/guides/cua-xfce-screenshot.png create mode 100644 src/agents/tools/computer-server-client.ts create mode 100644 src/agents/tools/computer-tool.ts diff --git a/docs/guides/computer-server-setup.md b/docs/guides/computer-server-setup.md new file mode 100644 index 000000000..6823e9208 --- /dev/null +++ b/docs/guides/computer-server-setup.md @@ -0,0 +1,176 @@ +# Computer-Server Setup for GUI Automation + +This guide explains how to set up [cua-computer-server](https://github.com/trycua/cua/tree/main/libs/python/computer-server) for desktop GUI automation with Clawdbot agents. + +## Overview + +The `computer` tool enables agents to: +- Take screenshots of the desktop +- Click at screen coordinates +- Type text and press keys +- Scroll and drag +- Control native applications + +## Setup Options + +### Option 1: Sandbox Mode (Recommended) + +Use Cua's pre-built desktop sandbox images. Computer-server is already installed and running. + +![cua-xfce desktop sandbox](./cua-xfce-screenshot.png) + +```yaml +# In your clawdbot config +agents: + defaults: + sandbox: + docker: + image: ghcr.io/trycua/cua-xfce:latest +``` + +Available sandbox images: + +| Image | Description | +|-------|-------------| +| `ghcr.io/trycua/cua-xfce:latest` | Linux + XFCE desktop | +| `ghcr.io/trycua/cua-ubuntu:latest` | Linux + Kasm desktop | + +For more options including Windows and Android, see [Cua Desktop Sandboxes](https://cua.ai/docs/cua/guide/get-started/what-is-desktop-sandbox#docker-sandboxes). + +### Option 2: Node Mode (Linux) + +For Linux nodes, you can set up computer-server to run as a daemon using supervisor. + +#### 1. Install computer-server + +```bash +pip install cua-computer-server +``` + +#### 2. Create startup script + +Create `/usr/local/bin/start-computer-server.sh`: + +```bash +#!/bin/bash +set -e + +# Wait for X server to be ready +echo "Waiting for X server to start..." +while ! xdpyinfo -display :0 >/dev/null 2>&1; do + sleep 1 +done +echo "X server is ready" + +# Start computer-server +export DISPLAY=:0 +python3 -m computer_server --port 8000 +``` + +Make it executable: + +```bash +chmod +x /usr/local/bin/start-computer-server.sh +``` + +#### 3. Configure supervisor + +Create `/etc/supervisor/conf.d/computer-server.conf`: + +```ini +[program:computer-server] +command=/usr/local/bin/start-computer-server.sh +user= +autorestart=true +stdout_logfile=/var/log/computer-server.log +stderr_logfile=/var/log/computer-server.error.log +``` + +#### 4. Start the service + +```bash +sudo supervisorctl reread +sudo supervisorctl update +sudo supervisorctl start computer-server +``` + +### Option 3: Node Mode (Windows/macOS) + +**TBD** - Setup instructions for Windows and macOS nodes will be added in a future update. + +## Usage + +Once computer-server is running, agents can use the `computer` tool: + +``` +Use the computer tool to take a screenshot and then click on the "File" menu. +``` + +The agent will: +1. Call `computer` with `action: "screenshot"` to see the screen +2. Identify the coordinates of "File" menu +3. Call `computer` with `action: "click"` and the coordinates + +## Configuration + +You can configure the computer-server URL in your Clawdbot config: + +```yaml +tools: + computer: + serverUrl: "http://localhost:8000" +``` + +Or per-agent: + +```yaml +agents: + my-agent: + tools: + computer: + serverUrl: "http://192.168.1.100:8000" +``` + +## MCP Alternative + +Computer-server also exposes an MCP (Model Context Protocol) interface at `/mcp`. This could be used as an alternative integration method if Clawdbot adds MCP client support in the future. + +To use computer-server as a standalone MCP server: + +```bash +python -m computer_server --mcp +``` + +## Troubleshooting + +### Connection refused + +Ensure computer-server is running and accessible: + +```bash +curl http://localhost:8000/status +``` + +Should return: `{"status": "ok", "os_type": "...", "features": [...]}` + +### No display + +If computer-server fails with display errors, ensure: +- X server is running (Linux) +- The `DISPLAY` environment variable is set correctly +- The user has permission to access the display + +### Sandbox not connecting + +Ensure the sandbox container has port 8000 exposed and the network is accessible from Clawdbot. + +## Security Considerations + +- **Sandbox mode**: Isolated container - safe for untrusted workloads +- **Node mode**: Controls the actual device screen - use only with trusted agents +- **Gateway mode**: Not supported - would give agents control of your actual desktop + +## Related + +- [cua-computer-server](https://github.com/trycua/cua/tree/main/libs/python/computer-server) - Desktop automation server +- [Cua Desktop Sandboxes](https://cua.ai/docs/cua/guide/get-started/what-is-desktop-sandbox) - Pre-built sandbox images diff --git a/docs/guides/cua-xfce-screenshot.png b/docs/guides/cua-xfce-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb4d36263364d237faaea0997af3e4337068f76 GIT binary patch literal 83345 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%0A6{0s^y`T3c2XY{ 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�I7$^aZW5cZ*QU;QYZ?r94^ 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 literal 0 HcmV?d00001 diff --git a/src/agents/clawdbot-tools.ts b/src/agents/clawdbot-tools.ts index 91de31937..96571efd9 100644 --- a/src/agents/clawdbot-tools.ts +++ b/src/agents/clawdbot-tools.ts @@ -6,6 +6,7 @@ import { createAgentsListTool } from "./tools/agents-list-tool.js"; import { createBrowserTool } from "./tools/browser-tool.js"; import { createCanvasTool } from "./tools/canvas-tool.js"; import type { AnyAgentTool } from "./tools/common.js"; +import { createComputerTool } from "./tools/computer-tool.js"; import { createCronTool } from "./tools/cron-tool.js"; import { createGatewayTool } from "./tools/gateway-tool.js"; import { createImageTool } from "./tools/image-tool.js"; @@ -25,6 +26,8 @@ export function createClawdbotTools(options?: { allowedControlUrls?: string[]; allowedControlHosts?: string[]; allowedControlPorts?: number[]; + /** URL of the computer-server for GUI automation (default: http://localhost:8000) */ + computerServerUrl?: string; agentSessionKey?: string; agentChannel?: GatewayMessageChannel; agentAccountId?: string; @@ -79,6 +82,10 @@ export function createClawdbotTools(options?: { allowedControlHosts: options?.allowedControlHosts, allowedControlPorts: options?.allowedControlPorts, }), + createComputerTool({ + defaultServerUrl: options?.computerServerUrl, + config: options?.config, + }), createCanvasTool(), createNodesTool({ agentSessionKey: options?.agentSessionKey, diff --git a/src/agents/tools/computer-server-client.ts b/src/agents/tools/computer-server-client.ts new file mode 100644 index 000000000..c920a7ff8 --- /dev/null +++ b/src/agents/tools/computer-server-client.ts @@ -0,0 +1,227 @@ +/** + * HTTP client for communicating with cua-computer-server. + * + * computer-server provides desktop automation capabilities via HTTP POST /cmd endpoint. + * Each command returns { success: boolean, ...result } or { success: false, error: string }. + * + * Note: computer-server also exposes an MCP interface at /mcp which could be used + * if Clawdbot adds MCP client support in the future. + * + * @see https://github.com/trycua/cua/tree/main/libs/python/computer-server + */ + +export interface ComputerServerConfig { + /** Base URL of the computer-server (default: http://localhost:8000) */ + baseUrl?: string; + /** Request timeout in milliseconds (default: 30000) */ + timeoutMs?: number; +} + +export interface ScreenshotResult { + /** Base64-encoded PNG image data */ + imageData: string; +} + +export interface ScreenSize { + width: number; + height: number; +} + +export interface CursorPosition { + x: number; + y: number; +} + +export interface CommandResult { + success: boolean; + error?: string; + [key: string]: unknown; +} + +export class ComputerServerError extends Error { + constructor( + message: string, + public readonly command: string, + public readonly statusCode?: number, + ) { + super(message); + this.name = "ComputerServerError"; + } +} + +export class ComputerServerClient { + private readonly baseUrl: string; + private readonly timeoutMs: number; + + constructor(config: ComputerServerConfig = {}) { + this.baseUrl = config.baseUrl ?? "http://localhost:8000"; + this.timeoutMs = config.timeoutMs ?? 30000; + } + + /** + * Take a screenshot of the desktop. + * @returns Base64-encoded PNG image data + */ + async screenshot(): Promise { + const result = await this.call("screenshot"); + return { imageData: result.image_data as string }; + } + + /** + * Get the screen dimensions. + */ + async getScreenSize(): Promise { + const result = await this.call("get_screen_size"); + const size = result.size as { width: number; height: number }; + return { + width: size.width, + height: size.height, + }; + } + + /** + * Get the current cursor position. + */ + async getCursorPosition(): Promise { + const result = await this.call("get_cursor_position"); + const position = result.position as { x: number; y: number }; + return { + x: position.x, + y: position.y, + }; + } + + /** + * Perform a left click at the specified coordinates. + * If coordinates are omitted, clicks at the current cursor position. + */ + async click(x?: number, y?: number): Promise { + await this.call("left_click", { x, y }); + } + + /** + * Perform a double click at the specified coordinates. + */ + async doubleClick(x?: number, y?: number): Promise { + await this.call("double_click", { x, y }); + } + + /** + * Perform a right click at the specified coordinates. + */ + async rightClick(x?: number, y?: number): Promise { + await this.call("right_click", { x, y }); + } + + /** + * Move the cursor to the specified coordinates. + */ + async moveCursor(x: number, y: number): Promise { + await this.call("move_cursor", { x, y }); + } + + /** + * Type text using the keyboard. + */ + async type(text: string): Promise { + await this.call("type_text", { text }); + } + + /** + * Press a single key (e.g., "Return", "Tab", "Escape"). + */ + async key(key: string): Promise { + await this.call("press_key", { key }); + } + + /** + * Press a combination of keys (e.g., ["cmd", "c"] for copy). + */ + async hotkey(keys: string[]): Promise { + await this.call("hotkey", { keys }); + } + + /** + * Scroll in a direction. + * @param direction - "up", "down", "left", or "right" + * @param clicks - Number of scroll clicks (default: 1) + */ + async scroll(direction: "up" | "down" | "left" | "right", clicks = 1): Promise { + if (direction === "down") { + await this.call("scroll_down", { clicks }); + } else if (direction === "up") { + await this.call("scroll_up", { clicks }); + } else { + // Horizontal scroll: use scroll(x, y) where positive x = right, negative = left + const x = direction === "right" ? 300 * clicks : -300 * clicks; + await this.call("scroll", { x, y: 0 }); + } + } + + /** + * Drag from current position to target coordinates. + */ + async dragTo(x: number, y: number, button = "left", duration = 0.5): Promise { + await this.call("drag_to", { x, y, button, duration }); + } + + /** + * Check if the computer-server is available and responding. + */ + async healthCheck(): Promise { + try { + const response = await fetch(`${this.baseUrl}/status`, { + method: "GET", + signal: AbortSignal.timeout(5000), + }); + return response.ok; + } catch { + return false; + } + } + + /** + * Send a command to the computer-server. + */ + private async call( + command: string, + params: Record = {}, + ): Promise { + // Filter out undefined values from params + const filteredParams = Object.fromEntries( + Object.entries(params).filter(([, v]) => v !== undefined), + ); + + const response = await fetch(`${this.baseUrl}/cmd`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ command, params: filteredParams }), + signal: AbortSignal.timeout(this.timeoutMs), + }); + + if (!response.ok) { + throw new ComputerServerError( + `HTTP ${response.status}: ${response.statusText}`, + command, + response.status, + ); + } + + // The /cmd endpoint returns SSE-style "data: {...}\n\n" format + const text = await response.text(); + const jsonMatch = text.match(/^data:\s*(.+)$/m); + if (!jsonMatch) { + throw new ComputerServerError(`Invalid response format from computer-server`, command); + } + + const result = JSON.parse(jsonMatch[1]) as CommandResult; + + if (!result.success) { + throw new ComputerServerError(result.error ?? `Command '${command}' failed`, command); + } + + return result; + } +} diff --git a/src/agents/tools/computer-tool.ts b/src/agents/tools/computer-tool.ts new file mode 100644 index 000000000..719df358d --- /dev/null +++ b/src/agents/tools/computer-tool.ts @@ -0,0 +1,312 @@ +/** + * Computer tool for GUI automation via cua-computer-server. + * + * Enables agents to take screenshots, click, type, scroll, and perform + * other desktop automation actions on sandboxes or nodes running computer-server. + * + * @see https://github.com/trycua/cua/tree/main/libs/python/computer-server + */ + +import { Type } from "@sinclair/typebox"; + +import type { ClawdbotConfig } from "../../config/config.js"; +import { stringEnum } from "../schema/typebox.js"; +import type { AnyAgentTool } from "./common.js"; +import { imageResult, jsonResult, readNumberParam, readStringParam } from "./common.js"; +import { ComputerServerClient, ComputerServerError } from "./computer-server-client.js"; + +const COMPUTER_ACTIONS = [ + "screenshot", + "click", + "double_click", + "right_click", + "type", + "key", + "hotkey", + "scroll", + "move", + "drag", + "get_screen_size", + "get_cursor_position", +] as const; + +const SCROLL_DIRECTIONS = ["up", "down", "left", "right"] as const; + +const ComputerToolSchema = Type.Object({ + action: stringEnum(COMPUTER_ACTIONS, { + description: + "Action to perform: screenshot, click, double_click, right_click, type, key, hotkey, scroll, move, drag, get_screen_size, get_cursor_position", + }), + + // Coordinates (for click, double_click, right_click, move, scroll) + x: Type.Optional(Type.Number({ description: "X coordinate in pixels" })), + y: Type.Optional(Type.Number({ description: "Y coordinate in pixels" })), + + // Typing + text: Type.Optional(Type.String({ description: "Text to type (for 'type' action)" })), + + // Key press + key: Type.Optional( + Type.String({ + description: "Key to press (for 'key' action), e.g., 'Return', 'Tab', 'Escape'", + }), + ), + + // Hotkey + keys: Type.Optional( + Type.Array(Type.String(), { + description: "Keys for hotkey combination (for 'hotkey' action), e.g., ['cmd', 'c']", + }), + ), + + // Scroll + direction: Type.Optional( + stringEnum(SCROLL_DIRECTIONS, { + description: "Scroll direction (for 'scroll' action): up, down, left, right", + }), + ), + amount: Type.Optional( + Type.Number({ + description: "Scroll amount in clicks (for 'scroll' action), default: 1", + }), + ), + + // Drag + end_x: Type.Optional(Type.Number({ description: "End X coordinate for drag action" })), + end_y: Type.Optional(Type.Number({ description: "End Y coordinate for drag action" })), + + // Connection + computer_server_url: Type.Optional( + Type.String({ + description: + "URL of the computer-server (default: http://localhost:8000). Usually set automatically based on sandbox/node configuration.", + }), + ), +}); + +export type ComputerToolOptions = { + /** Default computer-server URL */ + defaultServerUrl?: string; + /** Clawdbot configuration */ + config?: ClawdbotConfig; +}; + +export function createComputerTool(options?: ComputerToolOptions): AnyAgentTool { + return { + label: "Computer", + name: "computer", + description: `Control a computer's GUI - take screenshots, click, type, scroll, and more. + +Use this tool to interact with desktop applications running in a sandbox or on a connected node. + +**Actions:** +- \`screenshot\`: Capture the current screen state. Always do this first to see what's on screen. +- \`click\`: Left-click at coordinates (x, y) +- \`double_click\`: Double-click at coordinates (x, y) +- \`right_click\`: Right-click at coordinates (x, y) +- \`type\`: Type text at the current cursor position +- \`key\`: Press a single key (e.g., "Return", "Tab", "Escape") +- \`hotkey\`: Press a key combination (e.g., ["cmd", "c"] for copy) +- \`scroll\`: Scroll in a direction (up, down, left, right) +- \`move\`: Move cursor to coordinates without clicking +- \`drag\`: Drag from (x, y) to (end_x, end_y) +- \`get_screen_size\`: Get screen dimensions +- \`get_cursor_position\`: Get current cursor position + +**Tips:** +- Always take a screenshot first to understand the current screen state +- Use coordinates from screenshots to click on UI elements +- After performing actions, take another screenshot to verify the result`, + parameters: ComputerToolSchema, + execute: async (_toolCallId, params) => { + const action = readStringParam(params as Record, "action", { + required: true, + }); + const serverUrl = + readStringParam(params as Record, "computer_server_url") ?? + options?.defaultServerUrl ?? + "http://localhost:8000"; + + const client = new ComputerServerClient({ baseUrl: serverUrl }); + + try { + switch (action) { + case "screenshot": { + const result = await client.screenshot(); + return await imageResult({ + label: "Screenshot", + path: "screenshot.png", + base64: result.imageData, + mimeType: "image/png", + extraText: "Screenshot captured successfully", + }); + } + + case "click": { + const x = readNumberParam(params as Record, "x"); + const y = readNumberParam(params as Record, "y"); + await client.click(x, y); + return jsonResult({ + success: true, + action: "click", + coordinates: x !== undefined && y !== undefined ? { x, y } : "current position", + }); + } + + case "double_click": { + const x = readNumberParam(params as Record, "x"); + const y = readNumberParam(params as Record, "y"); + await client.doubleClick(x, y); + return jsonResult({ + success: true, + action: "double_click", + coordinates: x !== undefined && y !== undefined ? { x, y } : "current position", + }); + } + + case "right_click": { + const x = readNumberParam(params as Record, "x"); + const y = readNumberParam(params as Record, "y"); + await client.rightClick(x, y); + return jsonResult({ + success: true, + action: "right_click", + coordinates: x !== undefined && y !== undefined ? { x, y } : "current position", + }); + } + + case "type": { + const text = readStringParam(params as Record, "text", { + required: true, + label: "text", + }); + await client.type(text); + return jsonResult({ + success: true, + action: "type", + text, + }); + } + + case "key": { + const key = readStringParam(params as Record, "key", { + required: true, + label: "key", + }); + await client.key(key); + return jsonResult({ + success: true, + action: "key", + key, + }); + } + + case "hotkey": { + const keys = params.keys as string[] | undefined; + if (!keys || !Array.isArray(keys) || keys.length === 0) { + throw new Error("keys array required for hotkey action"); + } + await client.hotkey(keys); + return jsonResult({ + success: true, + action: "hotkey", + keys, + }); + } + + case "scroll": { + const direction = readStringParam(params as Record, "direction", { + required: true, + label: "direction", + }) as "up" | "down" | "left" | "right"; + const amount = readNumberParam(params as Record, "amount") ?? 1; + await client.scroll(direction, amount); + return jsonResult({ + success: true, + action: "scroll", + direction, + amount, + }); + } + + case "move": { + const x = readNumberParam(params as Record, "x", { + required: true, + label: "x coordinate", + })!; + const y = readNumberParam(params as Record, "y", { + required: true, + label: "y coordinate", + })!; + await client.moveCursor(x, y); + return jsonResult({ + success: true, + action: "move", + coordinates: { x, y }, + }); + } + + case "drag": { + const x = readNumberParam(params as Record, "x", { + required: true, + label: "start x coordinate", + })!; + const y = readNumberParam(params as Record, "y", { + required: true, + label: "start y coordinate", + })!; + const endX = readNumberParam(params as Record, "end_x", { + required: true, + label: "end x coordinate", + })!; + const endY = readNumberParam(params as Record, "end_y", { + required: true, + label: "end y coordinate", + })!; + // Move to start position first, then drag + await client.moveCursor(x, y); + await client.dragTo(endX, endY); + return jsonResult({ + success: true, + action: "drag", + from: { x, y }, + to: { x: endX, y: endY }, + }); + } + + case "get_screen_size": { + const size = await client.getScreenSize(); + return jsonResult({ + success: true, + action: "get_screen_size", + width: size.width, + height: size.height, + }); + } + + case "get_cursor_position": { + const pos = await client.getCursorPosition(); + return jsonResult({ + success: true, + action: "get_cursor_position", + x: pos.x, + y: pos.y, + }); + } + + default: + throw new Error(`Unknown action: ${action}`); + } + } catch (error) { + if (error instanceof ComputerServerError) { + return jsonResult({ + success: false, + error: error.message, + command: error.command, + }); + } + throw error; + } + }, + }; +} From e8b99634378aee851d2244700e3d0d5dafd521ec Mon Sep 17 00:00:00 2001 From: f-trycua Date: Sun, 25 Jan 2026 22:39:56 -0800 Subject: [PATCH 2/3] chore: re-trigger CI (flaky macOS test worker) From 438c80b7587264759f936a5dc66ad4914c230afe Mon Sep 17 00:00:00 2001 From: f-trycua Date: Mon, 26 Jan 2026 15:56:22 -0800 Subject: [PATCH 3/3] refactor: move computer tool to cua-computer plugin Move GUI automation from core to a standalone plugin. This keeps the core lean and lets users opt-in when they need computer-use capabilities. Plugin provides: - Screenshot capture - Mouse clicks (left, right, double) - Keyboard input (type, key, hotkey) - Scrolling and dragging - Cursor position/screen size queries Enable via config: ```yaml plugins: cua-computer: serverUrl: "http://localhost:8000" ``` --- extensions/cua-computer/clawdbot.plugin.json | 22 +++++++++++++ .../cua-computer}/computer-server-client.ts | 0 .../cua-computer}/computer-tool.ts | 8 ++--- extensions/cua-computer/index.ts | 33 +++++++++++++++++++ extensions/cua-computer/package.json | 6 ++++ src/agents/clawdbot-tools.ts | 7 ---- 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 extensions/cua-computer/clawdbot.plugin.json rename {src/agents/tools => extensions/cua-computer}/computer-server-client.ts (100%) rename {src/agents/tools => extensions/cua-computer}/computer-tool.ts (97%) create mode 100644 extensions/cua-computer/index.ts create mode 100644 extensions/cua-computer/package.json diff --git a/extensions/cua-computer/clawdbot.plugin.json b/extensions/cua-computer/clawdbot.plugin.json new file mode 100644 index 000000000..bbccc202d --- /dev/null +++ b/extensions/cua-computer/clawdbot.plugin.json @@ -0,0 +1,22 @@ +{ + "id": "cua-computer", + "name": "Cua Computer", + "description": "GUI automation via cua-computer-server - screenshots, clicks, typing, scrolling", + "version": "0.1.0", + "configSchema": { + "type": "object", + "properties": { + "serverUrl": { + "type": "string", + "description": "computer-server URL (default: http://localhost:8000)" + } + } + }, + "uiHints": { + "serverUrl": { + "label": "Server URL", + "placeholder": "http://localhost:8000", + "help": "URL of the cua-computer-server instance" + } + } +} diff --git a/src/agents/tools/computer-server-client.ts b/extensions/cua-computer/computer-server-client.ts similarity index 100% rename from src/agents/tools/computer-server-client.ts rename to extensions/cua-computer/computer-server-client.ts diff --git a/src/agents/tools/computer-tool.ts b/extensions/cua-computer/computer-tool.ts similarity index 97% rename from src/agents/tools/computer-tool.ts rename to extensions/cua-computer/computer-tool.ts index 719df358d..875f922d9 100644 --- a/src/agents/tools/computer-tool.ts +++ b/extensions/cua-computer/computer-tool.ts @@ -9,10 +9,10 @@ import { Type } from "@sinclair/typebox"; -import type { ClawdbotConfig } from "../../config/config.js"; -import { stringEnum } from "../schema/typebox.js"; -import type { AnyAgentTool } from "./common.js"; -import { imageResult, jsonResult, readNumberParam, readStringParam } from "./common.js"; +import type { ClawdbotConfig } from "../../src/config/config.js"; +import { stringEnum } from "../../src/agents/schema/typebox.js"; +import type { AnyAgentTool } from "../../src/agents/tools/common.js"; +import { imageResult, jsonResult, readNumberParam, readStringParam } from "../../src/agents/tools/common.js"; import { ComputerServerClient, ComputerServerError } from "./computer-server-client.js"; const COMPUTER_ACTIONS = [ diff --git a/extensions/cua-computer/index.ts b/extensions/cua-computer/index.ts new file mode 100644 index 000000000..fd3408371 --- /dev/null +++ b/extensions/cua-computer/index.ts @@ -0,0 +1,33 @@ +/** + * Cua Computer Plugin + * + * Provides GUI automation via cua-computer-server - screenshots, clicks, typing, scrolling. + * + * @see https://github.com/trycua/cua/tree/main/libs/python/computer-server + */ + +import type { ClawdbotPluginDefinition } from "../../src/plugins/types.js"; +import { createComputerTool } from "./computer-tool.js"; + +interface CuaComputerConfig { + serverUrl?: string; +} + +const plugin: ClawdbotPluginDefinition = { + id: "cua-computer", + name: "Cua Computer", + description: "GUI automation via cua-computer-server", + + register(api) { + const config = api.pluginConfig as CuaComputerConfig | undefined; + + api.registerTool( + createComputerTool({ + defaultServerUrl: config?.serverUrl, + config: api.config, + }), + ); + }, +}; + +export default plugin; diff --git a/extensions/cua-computer/package.json b/extensions/cua-computer/package.json new file mode 100644 index 000000000..6563fcaaa --- /dev/null +++ b/extensions/cua-computer/package.json @@ -0,0 +1,6 @@ +{ + "name": "@clawdbot/plugin-cua-computer", + "version": "0.1.0", + "type": "module", + "main": "index.ts" +} diff --git a/src/agents/clawdbot-tools.ts b/src/agents/clawdbot-tools.ts index 96571efd9..91de31937 100644 --- a/src/agents/clawdbot-tools.ts +++ b/src/agents/clawdbot-tools.ts @@ -6,7 +6,6 @@ import { createAgentsListTool } from "./tools/agents-list-tool.js"; import { createBrowserTool } from "./tools/browser-tool.js"; import { createCanvasTool } from "./tools/canvas-tool.js"; import type { AnyAgentTool } from "./tools/common.js"; -import { createComputerTool } from "./tools/computer-tool.js"; import { createCronTool } from "./tools/cron-tool.js"; import { createGatewayTool } from "./tools/gateway-tool.js"; import { createImageTool } from "./tools/image-tool.js"; @@ -26,8 +25,6 @@ export function createClawdbotTools(options?: { allowedControlUrls?: string[]; allowedControlHosts?: string[]; allowedControlPorts?: number[]; - /** URL of the computer-server for GUI automation (default: http://localhost:8000) */ - computerServerUrl?: string; agentSessionKey?: string; agentChannel?: GatewayMessageChannel; agentAccountId?: string; @@ -82,10 +79,6 @@ export function createClawdbotTools(options?: { allowedControlHosts: options?.allowedControlHosts, allowedControlPorts: options?.allowedControlPorts, }), - createComputerTool({ - defaultServerUrl: options?.computerServerUrl, - config: options?.config, - }), createCanvasTool(), createNodesTool({ agentSessionKey: options?.agentSessionKey,