UI-TARS-desktop插件开发API:扩展功能的编程接口详解
引言:释放UI-TARS-desktop的扩展能力
你是否在使用UI-TARS-desktop时遇到功能局限?是否需要定制化界面交互或集成专有系统?本文将系统解析UI-TARS-desktop插件开发API,帮助开发者构建强大的扩展功能。通过本文,你将掌握:
- 核心API架构:理解GUIAgent、Operator和UITarsModel的协作机制
- 插件开发全流程:从环境搭建到功能发布的完整步骤
- 高级扩展技术:自定义操作器、模型集成和错误处理策略
- 实战案例解析:通过NutJSOperator实现跨平台桌面控制
核心API架构解析
UI-TARS-desktop插件系统基于三层架构设计,通过松耦合的接口实现高度可扩展性。
类关系模型
核心组件职责
| 组件 | 职责 | 关键方法 |
|---|---|---|
| GUIAgent | 协调核心工作流 | run()、pause()、resume()、stop() |
| Operator | 处理系统交互 | screenshot()、execute() |
| UITarsModel | 管理模型交互 | invoke()、reset() |
工作流程时序
开发环境搭建
环境准备清单
| 工具 | 版本要求 | 用途 |
|---|---|---|
| Node.js | ≥16.0.0 | 运行环境 |
| npm/yarn | ≥8.0.0 | 包管理 |
| TypeScript | ≥5.0.0 | 类型检查 |
| @rslib/core | ≥0.5.4 | 构建工具 |
| vitest | ≥3.0.0 | 单元测试 |
初始化项目
mkdir ui-tars-plugin && cd ui-tars-plugin
npm init -y
修改package.json配置:
{
"name": "ui-tars-custom-operator",
"version": "1.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"scripts": {
"dev": "rslib build --watch",
"build": "rsbuild",
"test": "vitest"
},
"peerDependencies": {
"@ui-tars/sdk": "^1.2.0-beta.17"
},
"devDependencies": {
"@ui-tars/sdk": "^1.2.0-beta.17",
"@rslib/core": "^0.5.4",
"typescript": "^5.7.2",
"vitest": "^3.0.2"
}
}
基础插件开发
创建自定义Operator
Operator是插件开发的核心,需要实现屏幕捕获和动作执行两大核心能力。
import { Operator, ScreenshotOutput, ExecuteParams, ExecuteOutput } from '@ui-tars/sdk';
export class CustomOperator implements Operator {
// 定义动作空间描述
static MANUAL = {
ACTION_SPACES: [
'click(start_box="") # 点击指定坐标区域',
'type(content="") # 输入文本内容',
'scroll(direction="") # 滚动页面',
'finished() # 完成任务'
]
};
async screenshot(): Promise<ScreenshotOutput> {
// 实现屏幕捕获逻辑
return {
base64: 'data:image/png;base64,...', // 实际项目中替换为真实截图
scaleFactor: window.devicePixelRatio || 1
};
}
async execute(params: ExecuteParams): Promise<ExecuteOutput> {
const { parsedPrediction } = params;
switch (parsedPrediction.action_type) {
case 'click':
return this.handleClick(parsedPrediction.action_inputs);
case 'type':
return this.handleType(parsedPrediction.action_inputs);
case 'finished':
return { status: 'END' };
default:
throw new Error(`不支持的动作类型: ${parsedPrediction.action_type}`);
}
}
private handleClick(inputs: Record<string, any>): ExecuteOutput {
// 实现点击逻辑
const { start_box } = inputs;
const [x, y] = start_box.match(/\d+/g)?.map(Number) || [0, 0];
// 实际点击操作实现...
return { status: 'SUCCESS' };
}
private handleType(inputs: Record<string, any>): ExecuteOutput {
// 实现文本输入逻辑
const { content } = inputs;
// 实际输入操作实现...
return { status: 'SUCCESS' };
}
}
集成自定义Operator到GUIAgent
import { GUIAgent } from '@ui-tars/sdk';
import { CustomOperator } from './CustomOperator';
// 配置模型参数
const modelConfig = {
baseURL: 'https://your-model-endpoint.com',
apiKey: 'your-api-key',
model: 'ui-tars-13b'
};
// 创建GUIAgent实例
const agent = new GUIAgent({
model: modelConfig,
operator: new CustomOperator(),
systemPrompt: `
你是一个UI自动化助手,能够通过以下动作控制界面:
${CustomOperator.MANUAL.ACTION_SPACES.join('\n')}
`,
onData: ({ data }) => {
console.log('Agent状态更新:', data.status);
},
onError: ({ error }) => {
console.error('Agent错误:', error);
},
maxLoopCount: 30 // 最大循环次数限制
});
// 启动Agent
agent.run('打开浏览器并访问https://example.com');
// 5秒后暂停Agent
setTimeout(() => {
agent.pause();
console.log('Agent已暂停');
// 3秒后恢复Agent
setTimeout(() => {
agent.resume();
console.log('Agent已恢复');
}, 3000);
}, 5000);
高级功能开发
自定义模型集成
通过扩展UITarsModel类实现自定义模型集成:
import { UITarsModel, InvokeParams } from '@ui-tars/sdk';
class CustomVisionModel extends UITarsModel {
constructor(private config: { apiKey: string }) {
super(config);
}
async invoke(params: InvokeParams): Promise<any> {
// 实现自定义模型调用逻辑
const response = await fetch('https://your-custom-model.com/v1/invoke', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`
},
body: JSON.stringify({
prompt: params.prompt,
images: params.images,
screenContext: params.screenContext
})
});
const result = await response.json();
// 转换结果为UI-TARS期望的格式
return {
prediction: result.action,
parsedPredictions: [{
action_type: result.actionType,
action_inputs: result.actionParams,
thought: result.thoughtProcess,
reflection: result.reflection
}]
};
}
}
// 使用自定义模型
const customModel = new CustomVisionModel({
apiKey: 'your-custom-model-api-key'
});
const agent = new GUIAgent({
model: customModel,
operator: new CustomOperator(),
// ...其他配置
});
错误处理与重试机制
UI-TARS SDK内置多层次错误处理机制,可通过配置实现健壮的插件:
const agent = new GUIAgent({
// ...其他配置
retry: {
screenshot: {
maxRetries: 3,
onRetry: (error, attempt) => {
console.log(`截图重试 ${attempt}/3: ${error.message}`);
}
},
execute: {
maxRetries: 2,
minTimeout: 2000
}
},
onError: ({ data, error }) => {
switch (error.type) {
case 'SCREENSHOT_RETRY_ERROR':
console.error('截图失败超过最大重试次数');
// 实现恢复策略...
break;
case 'EXECUTE_RETRY_ERROR':
console.error('执行动作失败超过最大重试次数');
// 实现恢复策略...
break;
default:
console.error(`Agent错误: ${error.message}`);
}
}
});
状态管理与生命周期控制
GUIAgent提供完整的生命周期管理接口:
// 状态流转图

```typescript
// 完整的生命周期控制示例
const abortController = new AbortController();
const agent = new GUIAgent({
// ...其他配置
signal: abortController.signal,
onData: ({ data }) => {
console.log('当前状态:', data.status);
// 监听状态变化
if (data.status === 'MAX_LOOP') {
console.log('达到最大循环次数');
agent.stop();
}
}
});
// 启动任务
agent.run('复杂的自动化任务...');
// 监听用户输入终止任务
process.on('SIGINT', () => {
abortController.abort();
// 或者调用agent.stop()
agent.stop();
});
实战案例:跨平台自动化操作器
NutJSOperator实现分析
NutJSOperator是UI-TARS-desktop提供的默认操作器,基于nut.js实现跨平台桌面控制:
import { Operator } from '@ui-tars/sdk';
import { mouse, keyboard, screen, Point } from '@nut-tree/nut-js';
export class NutJSOperator implements Operator {
static MANUAL = {
ACTION_SPACES: [
'click(start_box="(x,y)") # 点击坐标(x,y)',
'double_click(start_box="(x,y)") # 双击坐标(x,y)',
'right_click(start_box="(x,y)") # 右键点击坐标(x,y)',
'type(content="text") # 输入文本',
'hotkey(keys="ctrl+c") # 按下热键组合',
'scroll(direction="up|down", amount=10) # 滚动页面'
]
};
async screenshot(): Promise<ScreenshotOutput> {
// 获取主屏幕
const mainScreen = await screen.grab();
const imageBuffer = await mainScreen.toBuffer();
return {
base64: `data:image/png;base64,${imageBuffer.toString('base64')}`,
scaleFactor: screen.scaleFactor
};
}
async execute(params: ExecuteParams): Promise<ExecuteOutput> {
const { parsedPrediction, screenWidth, screenHeight, scaleFactor } = params;
// 坐标转换:模型输出坐标 -> 实际屏幕坐标
const convertCoordinates = (box: string): Point => {
const [x, y] = box.match(/\d+/g)?.map(Number) || [0, 0];
return new Point(x / scaleFactor, y / scaleFactor);
};
switch (parsedPrediction.action_type) {
case 'click':
const clickPoint = convertCoordinates(parsedPrediction.action_inputs.start_box);
await mouse.move(clickPoint);
await mouse.click();
return { status: 'SUCCESS' };
case 'type':
await keyboard.type(parsedPrediction.action_inputs.content);
return { status: 'SUCCESS' };
case 'hotkey':
const keys = parsedPrediction.action_inputs.keys.split('+');
await keyboard.pressKey(...keys);
await keyboard.releaseKey(...keys);
return { status: 'SUCCESS' };
// 其他动作实现...
default:
return { status: 'UNKNOWN_ACTION' };
}
}
}
自定义操作器开发指南
开发自定义操作器需遵循以下最佳实践:
-
接口兼容性
- 严格实现
Operator接口的screenshot()和execute()方法 - 确保返回类型符合
ScreenshotOutput和ExecuteOutput定义
- 严格实现
-
错误处理
- 实现动作执行的重试机制
- 提供详细的错误信息以便调试
-
性能优化
- 截图操作使用高效编码
- 坐标转换考虑多屏幕和DPI适配
-
安全性
- 验证所有输入参数
- 实现操作沙箱限制危险动作
插件测试与调试
单元测试策略
import { describe, it, expect, vi } from 'vitest';
import { CustomOperator } from './CustomOperator';
describe('CustomOperator', () => {
const operator = new CustomOperator();
it('should generate correct action spaces', () => {
expect(CustomOperator.MANUAL.ACTION_SPACES).toContain(
'click(start_box="") # 点击指定坐标区域'
);
});
it('should handle click action', async () => {
// Mock实现
operator['handleClick'] = vi.fn().mockResolvedValue({ status: 'SUCCESS' });
const result = await operator.execute({
parsedPrediction: {
action_type: 'click',
action_inputs: { start_box: '(100,200)' },
thought: '',
reflection: null
},
// 其他必要参数...
});
expect(result.status).toBe('SUCCESS');
expect(operator['handleClick']).toHaveBeenCalled();
});
});
集成测试与调试
// agent.test.ts
import { describe, it, expect, vi } from 'vitest';
import { GUIAgent } from '@ui-tars/sdk';
import { CustomOperator } from './CustomOperator';
describe('GUIAgent with CustomOperator', () => {
it('should complete task successfully', async () => {
const mockOperator = new CustomOperator();
mockOperator.screenshot = vi.fn().mockResolvedValue({
base64: 'data:image/png;base64,mock',
scaleFactor: 1
});
mockOperator.execute = vi.fn().mockResolvedValue({
status: 'END' // 模拟任务完成
});
const onData = vi.fn();
const agent = new GUIAgent({
model: {
baseURL: 'https://mock-model.com',
apiKey: 'test-key',
model: 'test-model'
},
operator: mockOperator,
onData
});
// Mock模型调用
agent['model'].invoke = vi.fn().mockResolvedValue({
prediction: 'finished()',
parsedPredictions: [{
action_type: 'finished',
action_inputs: {},
thought: '',
reflection: null
}]
});
await agent.run('测试任务');
expect(onData).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({
status: 'END'
})
})
);
});
});
发布与分发
插件打包规范
{
"name": "@your-org/ui-tars-custom-operator",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist", "README.md"],
"keywords": ["ui-tars", "plugin", "operator"],
"peerDependencies": {
"@ui-tars/sdk": "^1.2.0-beta.17"
},
"publishConfig": {
"access": "public"
}
}
发布流程
-
构建项目
npm run build -
版本管理
npm version patch # 或 minor/major -
发布到npm
npm publish
总结与展望
UI-TARS-desktop插件开发API为扩展应用功能提供了强大而灵活的框架。通过本文介绍的API架构、开发流程和实战案例,开发者可以构建各种自定义扩展,满足特定业务需求。
未来,UI-TARS-desktop插件系统将支持更多功能:
- 更丰富的生命周期钩子:提供更多扩展点
- 插件市场:简化插件发现和安装
- 可视化开发工具:降低插件开发门槛
- 高级权限控制:细粒度的操作权限管理
立即开始探索UI-TARS-desktop插件开发,释放自动化控制的无限可能!
附录:API参考速查表
GUIAgent配置选项
| 参数 | 类型 | 描述 | 默认值 |
|---|---|---|---|
model | ModelConfig \| UITarsModel | 模型配置或实例 | 必需 |
operator | Operator | 操作器实例 | 必需 |
systemPrompt | string | 系统提示词 | 默认模板 |
maxLoopCount | number | 最大循环次数 | 25 |
signal | AbortSignal | 终止信号 | - |
logger | Logger | 日志记录器 | console |
onData | (data) => void | 数据回调 | - |
onError | (error) => void | 错误回调 | - |
Operator接口定义
interface Operator {
screenshot(): Promise<ScreenshotOutput>;
execute(params: ExecuteParams): Promise<ExecuteOutput>;
}
interface ScreenshotOutput {
base64: string;
scaleFactor: number;
}
interface ExecuteParams {
prediction: string;
parsedPrediction: {
action_type: string;
action_inputs: Record<string, any>;
thought: string;
reflection: string | null;
};
screenWidth: number;
screenHeight: number;
scaleFactor: number;
factors: [number, number];
}
错误类型参考
| 错误类型 | 描述 | 处理策略 |
|---|---|---|
SCREENSHOT_RETRY_ERROR | 截图失败 | 检查系统权限 |
EXECUTE_RETRY_ERROR | 动作执行失败 | 验证动作参数 |
MODEL_SERVICE_ERROR | 模型服务错误 | 检查网络连接 |
REACH_MAXLOOP_ERROR | 达到最大循环 | 优化任务步骤 |
点赞+收藏+关注,获取UI-TARS-desktop插件开发最新动态!下一期将带来《插件安全最佳实践》,敬请期待。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



