@amaster.ai/pi-computer-use 0.1.2-beta.2 → 0.1.2-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/bin/darwin-arm64/cua-driver +0 -0
- package/bin/darwin-x64/cua-driver +0 -0
- package/bin/linux-x64/cua-driver +0 -0
- package/bin/win32-arm64/cua-driver.exe +0 -0
- package/bin/win32-x64/cua-driver.exe +0 -0
- package/dist/config.d.ts +5 -19
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -6
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +162 -78
- package/dist/index.js.map +1 -1
- package/dist/mcp-client.d.ts +22 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +71 -0
- package/dist/mcp-client.js.map +1 -0
- package/package.json +15 -5
- package/dist/__tests__/computer-client.test.d.ts +0 -2
- package/dist/__tests__/computer-client.test.d.ts.map +0 -1
- package/dist/__tests__/computer-client.test.js +0 -174
- package/dist/__tests__/computer-client.test.js.map +0 -1
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.d.ts.map +0 -1
- package/dist/__tests__/index.test.js +0 -385
- package/dist/__tests__/index.test.js.map +0 -1
- package/dist/__tests__/server-process.test.d.ts +0 -2
- package/dist/__tests__/server-process.test.d.ts.map +0 -1
- package/dist/__tests__/server-process.test.js +0 -127
- package/dist/__tests__/server-process.test.js.map +0 -1
- package/dist/__tests__/vision.test.d.ts +0 -2
- package/dist/__tests__/vision.test.d.ts.map +0 -1
- package/dist/__tests__/vision.test.js +0 -36
- package/dist/__tests__/vision.test.js.map +0 -1
- package/dist/actions.d.ts +0 -15
- package/dist/actions.d.ts.map +0 -1
- package/dist/actions.js +0 -45
- package/dist/actions.js.map +0 -1
- package/dist/computer-client.d.ts +0 -13
- package/dist/computer-client.d.ts.map +0 -1
- package/dist/computer-client.js +0 -109
- package/dist/computer-client.js.map +0 -1
- package/dist/server-process.d.ts +0 -9
- package/dist/server-process.d.ts.map +0 -1
- package/dist/server-process.js +0 -76
- package/dist/server-process.js.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# @amaster.ai/pi-computer-use
|
|
2
|
+
|
|
3
|
+
pi-coding-agent extension that wraps [cua-driver-rs](https://github.com/trycua/cua/), exposing desktop automation tools with a `computer_use_` prefix.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Zero external dependencies** — pre-compiled cua-driver-rs binaries bundled for all platforms
|
|
8
|
+
- **MCP stdio communication** — spawns `cua-driver mcp` via `StdioClientTransport`, JSON-RPC over stdio
|
|
9
|
+
- **Dynamic tool discovery** — auto-discovers upstream MCP tools and registers with `computer_use_` prefix
|
|
10
|
+
- **Smart tool filtering** — excludes non-essential tools (agent cursor, recording, config), exposes 18 core tools
|
|
11
|
+
- **Optional visual analysis** — `computer_use_analyze_screenshot` via configurable vision model
|
|
12
|
+
- **Permission detection** — checks Accessibility & Screen Recording on startup, warns if not granted, and returns friendly guidance on permission errors
|
|
13
|
+
- **Cross-platform** — darwin-arm64/x64, linux-x64, win32-x64/arm64
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @amaster.ai/pi-computer-use
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Requires Node.js >= 20 and `@earendil-works/pi-coding-agent >= 0.74.0`.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Install the package and pi-coding-agent will automatically discover and load the extension. All tools are registered on `session_start`.
|
|
26
|
+
|
|
27
|
+
Configure via `.pi/settings.json` (project-level) or `~/.pi/agent/settings.json` (user-level) under the `"pi-computer-use"` key:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"pi-computer-use": {
|
|
32
|
+
"mode": "bundled"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
| Option | Type | Default | Description |
|
|
40
|
+
|--------|------|---------|-------------|
|
|
41
|
+
| `mode` | `'bundled' \| 'path'` | `'bundled'` | Binary resolution strategy |
|
|
42
|
+
| `binaryPath` | `string` | — | Custom cua-driver binary path (requires `mode: 'path'`) |
|
|
43
|
+
| `extraArgs` | `string[]` | — | Extra CLI arguments passed to cua-driver |
|
|
44
|
+
| `visionModel` | `VisionModelConfig` | — | Enable visual screenshot analysis |
|
|
45
|
+
|
|
46
|
+
### Vision Model (Optional)
|
|
47
|
+
|
|
48
|
+
Enable `computer_use_analyze_screenshot` by referencing a model already configured in Pi's model registry (`models.json`):
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"pi-computer-use": {
|
|
53
|
+
"visionModel": {
|
|
54
|
+
"provider": "openai",
|
|
55
|
+
"model": "gpt-4o"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The extension resolves API key, base URL, and headers from the model registry automatically — no need to duplicate credentials here.
|
|
62
|
+
|
|
63
|
+
## Exposed Tools (18)
|
|
64
|
+
|
|
65
|
+
### Core
|
|
66
|
+
|
|
67
|
+
| Tool | Description |
|
|
68
|
+
|------|-------------|
|
|
69
|
+
| `computer_use_screenshot` | Capture screen |
|
|
70
|
+
| `computer_use_click` | Click at coordinates |
|
|
71
|
+
| `computer_use_type_text` | Type text |
|
|
72
|
+
| `computer_use_press_key` | Press a keyboard key |
|
|
73
|
+
| `computer_use_scroll` | Scroll in a direction |
|
|
74
|
+
| `computer_use_hotkey` | Press key combination |
|
|
75
|
+
|
|
76
|
+
### Common
|
|
77
|
+
|
|
78
|
+
| Tool | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| `computer_use_double_click` | Double-click |
|
|
81
|
+
| `computer_use_right_click` | Right-click (context menu) |
|
|
82
|
+
| `computer_use_drag` | Drag from one point to another |
|
|
83
|
+
| `computer_use_get_screen_size` | Get screen dimensions |
|
|
84
|
+
| `computer_use_get_accessibility_tree` | Get accessibility tree for element discovery |
|
|
85
|
+
| `computer_use_set_value` | Set form field value directly |
|
|
86
|
+
| `computer_use_get_cursor_position` | Get current cursor position |
|
|
87
|
+
|
|
88
|
+
### Situational
|
|
89
|
+
|
|
90
|
+
| Tool | Description |
|
|
91
|
+
|------|-------------|
|
|
92
|
+
| `computer_use_list_apps` | List running applications |
|
|
93
|
+
| `computer_use_list_windows` | List open windows |
|
|
94
|
+
| `computer_use_get_window_state` | Get window state/position |
|
|
95
|
+
| `computer_use_launch_app` | Launch an application |
|
|
96
|
+
| `computer_use_kill_app` | Kill an application |
|
|
97
|
+
|
|
98
|
+
## Excluded Tools (15)
|
|
99
|
+
|
|
100
|
+
Agent cursor styling, recording/replay, config management, and redundant operations (covered by other tools) are filtered out.
|
|
101
|
+
|
|
102
|
+
## Permissions
|
|
103
|
+
|
|
104
|
+
On `session_start`, the extension checks macOS Accessibility and Screen Recording permissions via cua-driver's `check_permissions`. If not granted, a non-blocking warning is shown to the user.
|
|
105
|
+
|
|
106
|
+
When a tool call fails due to missing permissions (`ax_not_granted` / `sc_not_granted`), the extension returns a friendly message guiding the user to System Settings instead of a raw error.
|
|
107
|
+
|
|
108
|
+
## Supported Platforms
|
|
109
|
+
|
|
110
|
+
| Platform | Binary |
|
|
111
|
+
|----------|--------|
|
|
112
|
+
| macOS ARM64 | `bin/darwin-arm64/cua-driver` |
|
|
113
|
+
| macOS x64 | `bin/darwin-x64/cua-driver` |
|
|
114
|
+
| Linux x64 | `bin/linux-x64/cua-driver` |
|
|
115
|
+
| Windows x64 | `bin/win32-x64/cua-driver.exe` |
|
|
116
|
+
| Windows ARM64 | `bin/win32-arm64/cua-driver.exe` |
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
Apache-2.0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/config.d.ts
CHANGED
|
@@ -2,28 +2,14 @@ import { type PiSettingsOptions } from '@amaster.ai/pi-shared/settings';
|
|
|
2
2
|
export interface VisionModelConfig {
|
|
3
3
|
provider: string;
|
|
4
4
|
model: string;
|
|
5
|
-
apiKey?: string;
|
|
6
|
-
baseUrl?: string;
|
|
7
5
|
}
|
|
8
6
|
export interface ComputerUseConfig {
|
|
9
|
-
/** '
|
|
10
|
-
mode?: '
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
package?: string;
|
|
15
|
-
/** Extra CLI args for cua-computer-server */
|
|
7
|
+
/** 'bundled' uses the packaged binary, 'path' uses a custom binary path */
|
|
8
|
+
mode?: 'bundled' | 'path';
|
|
9
|
+
/** Custom cua-driver binary path (used when mode is 'path') */
|
|
10
|
+
binaryPath?: string;
|
|
11
|
+
/** Extra CLI args passed to cua-driver mcp */
|
|
16
12
|
extraArgs?: string[];
|
|
17
|
-
/** Server host (default: '127.0.0.1') */
|
|
18
|
-
host?: string;
|
|
19
|
-
/** Server port (default: 8000) */
|
|
20
|
-
port?: number;
|
|
21
|
-
/** API key — enables wss + auth for cloud/remote */
|
|
22
|
-
apiKey?: string;
|
|
23
|
-
/** VM name for cloud routing */
|
|
24
|
-
vmName?: string;
|
|
25
|
-
/** Auto-screenshot after each action (default: true) */
|
|
26
|
-
autoScreenshot?: boolean;
|
|
27
13
|
/** Vision model for screenshot analysis */
|
|
28
14
|
visionModel?: VisionModelConfig;
|
|
29
15
|
}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAMD,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAE3E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAKjF"}
|
package/dist/config.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { loadPiSettings } from '@amaster.ai/pi-shared/settings';
|
|
2
2
|
import { getAgentDir } from '@earendil-works/pi-coding-agent';
|
|
3
3
|
const DEFAULTS = {
|
|
4
|
-
mode: '
|
|
5
|
-
command: 'uvx',
|
|
6
|
-
package: 'cua-computer-server',
|
|
7
|
-
host: '127.0.0.1',
|
|
8
|
-
port: 8000,
|
|
9
|
-
autoScreenshot: true,
|
|
4
|
+
mode: 'bundled',
|
|
10
5
|
};
|
|
11
6
|
export function resolveConfig(config) {
|
|
12
7
|
return { ...DEFAULTS, ...config };
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA0B,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA0B,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAkB9D,MAAM,QAAQ,GAA+B;IAC3C,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,MAA0B;IACtD,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA2B;IAC5D,OAAO,cAAc,CAAoB,iBAAiB,EAAE;QAC1D,QAAQ,EAAE,WAAW,EAAE;QACvB,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AAEtF,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIxF,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAsB7C,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkLnE"}
|
package/dist/index.js
CHANGED
|
@@ -1,103 +1,187 @@
|
|
|
1
1
|
import { Type } from 'typebox';
|
|
2
|
-
import { dispatchAction } from './actions.js';
|
|
3
|
-
import { ComputerClient } from './computer-client.js';
|
|
4
2
|
import { loadConfigFromFile, resolveConfig } from './config.js';
|
|
5
|
-
import {
|
|
3
|
+
import { CuaDriverClient } from './mcp-client.js';
|
|
6
4
|
import { createPiVisionCaller } from './vision.js';
|
|
7
5
|
export { loadConfigFromFile, resolveConfig };
|
|
6
|
+
const TOOL_PREFIX = 'computer_use_';
|
|
7
|
+
const EXCLUDED_TOOLS = new Set([
|
|
8
|
+
'set_agent_cursor_enabled',
|
|
9
|
+
'set_agent_cursor_motion',
|
|
10
|
+
'set_agent_cursor_style',
|
|
11
|
+
'get_agent_cursor_state',
|
|
12
|
+
'set_recording',
|
|
13
|
+
'get_recording_state',
|
|
14
|
+
'replay_trajectory',
|
|
15
|
+
'check_permissions',
|
|
16
|
+
'get_config',
|
|
17
|
+
'set_config',
|
|
18
|
+
'move_cursor',
|
|
19
|
+
'zoom',
|
|
20
|
+
'type_text_chars',
|
|
21
|
+
'page',
|
|
22
|
+
'browser_eval',
|
|
23
|
+
]);
|
|
8
24
|
export default function computerUseExtension(pi) {
|
|
9
|
-
let config
|
|
10
|
-
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
let config;
|
|
26
|
+
let client;
|
|
27
|
+
let connected = false;
|
|
28
|
+
async function ensureConnected() {
|
|
29
|
+
if (!client)
|
|
30
|
+
throw new Error('pi-computer-use: session not started');
|
|
31
|
+
if (!connected) {
|
|
32
|
+
await client.connect();
|
|
33
|
+
connected = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function registerUpstreamTools() {
|
|
37
|
+
await ensureConnected();
|
|
38
|
+
const upstreamTools = await client.listAllTools();
|
|
39
|
+
for (const tool of upstreamTools) {
|
|
40
|
+
if (EXCLUDED_TOOLS.has(tool.name))
|
|
41
|
+
continue;
|
|
42
|
+
const prefixedName = `${TOOL_PREFIX}${tool.name}`;
|
|
43
|
+
const originalName = tool.name;
|
|
44
|
+
pi.registerTool({
|
|
45
|
+
name: prefixedName,
|
|
46
|
+
label: prefixedName,
|
|
47
|
+
description: tool.description ?? '',
|
|
48
|
+
parameters: Type.Unsafe(tool.inputSchema),
|
|
49
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
50
|
+
await ensureConnected();
|
|
51
|
+
const result = await client.callTool(originalName, params);
|
|
52
|
+
if (result.isError) {
|
|
53
|
+
const errorText = result.content?.map((c) => c.text ?? '').join('') ?? '';
|
|
54
|
+
const friendlyError = formatToolError(originalName, errorText, params);
|
|
55
|
+
if (friendlyError) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: 'text', text: friendlyError }],
|
|
58
|
+
details: undefined,
|
|
59
|
+
isError: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (originalName === 'screenshot' && config?.visionModel) {
|
|
64
|
+
const imageContent = result.content?.find((c) => c.type === 'image' && c.data);
|
|
65
|
+
if (imageContent?.data) {
|
|
66
|
+
const callVision = createPiVisionCaller(config.visionModel, ctx);
|
|
67
|
+
const analysis = await callVision('Describe the full screen: identify all visible windows, UI elements, buttons, text fields, and their positions.', imageContent.data, imageContent.mimeType ?? 'image/png');
|
|
68
|
+
return {
|
|
69
|
+
content: [{ type: 'text', text: analysis }],
|
|
70
|
+
details: undefined,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const content = [];
|
|
75
|
+
if (result.content) {
|
|
76
|
+
for (const item of result.content) {
|
|
77
|
+
if (item.type === 'text' && item.text) {
|
|
78
|
+
content.push({ type: 'text', text: item.text });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (content.length === 0) {
|
|
83
|
+
content.push({ type: 'text', text: 'Action executed.' });
|
|
84
|
+
}
|
|
85
|
+
return result.isError
|
|
86
|
+
? { content, details: undefined, isError: true }
|
|
87
|
+
: { content, details: undefined };
|
|
88
|
+
},
|
|
89
|
+
});
|
|
18
90
|
}
|
|
19
|
-
await client.connect();
|
|
20
|
-
started = true;
|
|
21
91
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
y: Type.Optional(Type.Number({ description: 'Y coordinate (click, double_click, move)' })),
|
|
34
|
-
button: Type.Optional(Type.String({ description: 'Mouse button: left | right (default: left)' })),
|
|
35
|
-
text: Type.Optional(Type.String({ description: 'Text to type (type action)' })),
|
|
36
|
-
keys: Type.Optional(Type.Array(Type.String(), { description: 'Keys to press (keypress action)' })),
|
|
37
|
-
scroll_x: Type.Optional(Type.Number({ description: 'Horizontal scroll amount' })),
|
|
38
|
-
scroll_y: Type.Optional(Type.Number({ description: 'Vertical scroll amount' })),
|
|
39
|
-
path: Type.Optional(Type.Array(Type.Array(Type.Number(), { minItems: 2, maxItems: 2 }), {
|
|
40
|
-
description: 'Drag path as [[x,y], ...] coordinates',
|
|
92
|
+
async function registerVisionTool() {
|
|
93
|
+
if (!config?.visionModel)
|
|
94
|
+
return;
|
|
95
|
+
const visionConfig = config.visionModel;
|
|
96
|
+
pi.registerTool({
|
|
97
|
+
name: `${TOOL_PREFIX}analyze_screenshot`,
|
|
98
|
+
label: `${TOOL_PREFIX}analyze_screenshot`,
|
|
99
|
+
description: 'Take a screenshot and analyze it visually using a vision model. Use when you need to identify elements by visual attributes (color, layout, position) or need precise pixel coordinates.',
|
|
100
|
+
parameters: Type.Object({
|
|
101
|
+
instruction: Type.Optional(Type.String({
|
|
102
|
+
description: 'What to identify or analyze visually (e.g., "Find the coordinates of the blue submit button").',
|
|
41
103
|
})),
|
|
42
|
-
command: Type.Optional(Type.String({ description: 'Shell command (run_command action)' })),
|
|
43
104
|
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (config.visionModel) {
|
|
50
|
-
const callVision = createPiVisionCaller(config.visionModel, ctx);
|
|
51
|
-
const analysis = await callVision('Describe the full screen: identify all visible windows, UI elements, buttons, text fields, and their positions.', screenshotBase64, 'image/png');
|
|
52
|
-
return { content: [{ type: 'text', text: analysis }], details: undefined };
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
content: [
|
|
56
|
-
{
|
|
57
|
-
type: 'text',
|
|
58
|
-
text: 'Screenshot captured (no vision model configured to analyze it).',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
details: undefined,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
const actionResult = await dispatchAction(client, params.action);
|
|
65
|
-
if (config.autoScreenshot !== false) {
|
|
66
|
-
const screenshotBase64 = await client.screenshot();
|
|
67
|
-
if (config.visionModel) {
|
|
68
|
-
const callVision = createPiVisionCaller(config.visionModel, ctx);
|
|
69
|
-
const analysis = await callVision('Describe the current screen state after the action. Focus on what changed and what is now visible.', screenshotBase64, 'image/png');
|
|
105
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
106
|
+
await ensureConnected();
|
|
107
|
+
const screenshotResult = await client.callTool('screenshot', {});
|
|
108
|
+
const imageContent = screenshotResult.content?.find((c) => c.type === 'image' && c.data);
|
|
109
|
+
if (!imageContent?.data) {
|
|
70
110
|
return {
|
|
71
|
-
content: [
|
|
72
|
-
{
|
|
73
|
-
type: 'text',
|
|
74
|
-
text: `${actionResult}\n\nScreen state:\n${analysis}`,
|
|
75
|
-
},
|
|
76
|
-
],
|
|
111
|
+
content: [{ type: 'text', text: 'Failed to capture screenshot.' }],
|
|
77
112
|
details: undefined,
|
|
113
|
+
isError: true,
|
|
78
114
|
};
|
|
79
115
|
}
|
|
116
|
+
const callVision = createPiVisionCaller(visionConfig, ctx);
|
|
117
|
+
const instruction = params.instruction ??
|
|
118
|
+
'Describe the full screen: identify all visible windows, UI elements, buttons, text fields, and their positions.';
|
|
119
|
+
const analysis = await callVision(instruction, imageContent.data, imageContent.mimeType ?? 'image/png');
|
|
80
120
|
return {
|
|
81
|
-
content: [{ type: 'text', text:
|
|
121
|
+
content: [{ type: 'text', text: analysis }],
|
|
82
122
|
details: undefined,
|
|
83
123
|
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
details: undefined,
|
|
88
|
-
};
|
|
89
|
-
},
|
|
90
|
-
});
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
91
127
|
pi.on('session_start', async (_event, ctx) => {
|
|
92
128
|
config = resolveConfig(loadConfigFromFile({ cwd: ctx.cwd }));
|
|
93
|
-
client = new
|
|
129
|
+
client = new CuaDriverClient(config);
|
|
130
|
+
connected = false;
|
|
131
|
+
await registerUpstreamTools();
|
|
132
|
+
await registerVisionTool();
|
|
133
|
+
try {
|
|
134
|
+
const permResult = await client.callTool('check_permissions', {});
|
|
135
|
+
const structured = permResult.structuredContent;
|
|
136
|
+
if (structured) {
|
|
137
|
+
if (!structured.accessibility) {
|
|
138
|
+
ctx.ui.notify('pi-computer-use: Accessibility not granted. Go to System Settings → Privacy & Security → Accessibility to enable.', 'warning');
|
|
139
|
+
}
|
|
140
|
+
if (!structured.screen_recording) {
|
|
141
|
+
ctx.ui.notify('pi-computer-use: Screen Recording not granted. Go to System Settings → Privacy & Security → Screen & System Audio Recording to enable.', 'warning');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// permission check is best-effort — do not block session start
|
|
147
|
+
}
|
|
94
148
|
});
|
|
95
149
|
pi.on('session_shutdown', async () => {
|
|
96
|
-
if (
|
|
150
|
+
if (connected && client) {
|
|
97
151
|
await client.close();
|
|
98
|
-
|
|
99
|
-
started = false;
|
|
152
|
+
connected = false;
|
|
100
153
|
}
|
|
101
154
|
});
|
|
102
155
|
}
|
|
156
|
+
function formatToolError(toolName, errorText, params) {
|
|
157
|
+
if (errorText.includes('ax_not_granted')) {
|
|
158
|
+
return 'Accessibility permission not granted. The user needs to enable it in System Settings → Privacy & Security → Accessibility, then restart the app.';
|
|
159
|
+
}
|
|
160
|
+
if (errorText.includes('sc_not_granted')) {
|
|
161
|
+
return 'Screen Recording permission not granted. The user needs to enable it in System Settings → Privacy & Security → Screen & System Audio Recording, then restart the app.';
|
|
162
|
+
}
|
|
163
|
+
if (toolName === 'screenshot' || errorText.includes('screencapture failed')) {
|
|
164
|
+
const windowId = params.window_id;
|
|
165
|
+
if (windowId !== undefined) {
|
|
166
|
+
if (errorText.includes('screencapture failed')) {
|
|
167
|
+
return [
|
|
168
|
+
`Screenshot failed for window ${windowId}. Possible causes:`,
|
|
169
|
+
'1. Screen Recording permission not granted — enable in System Settings → Privacy & Security → Screen & System Audio Recording, then restart the app.',
|
|
170
|
+
'2. The window_id is stale — the window may have been closed or recreated (e.g. after navigation in Electron apps). Re-fetch window list to get current IDs.',
|
|
171
|
+
'3. The window is minimized or not yet rendered.',
|
|
172
|
+
`Try capturing without window_id (full screen) as a fallback, or verify the window still exists.`,
|
|
173
|
+
].join('\n');
|
|
174
|
+
}
|
|
175
|
+
if (errorText.includes('empty output')) {
|
|
176
|
+
return `Screenshot captured an empty image for window ${windowId}. The window may be minimized, fully transparent, or off-screen. Try restoring the window first.`;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
if (errorText.includes('screencapture failed')) {
|
|
181
|
+
return 'Screenshot failed for the main display. Screen Recording permission may not be granted — enable in System Settings → Privacy & Security → Screen & System Audio Recording, then restart the app.';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
103
187
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { ComputerUseConfig } from './config.js';
|
|
3
|
+
export declare class CuaDriverClient {
|
|
4
|
+
private client;
|
|
5
|
+
private transport;
|
|
6
|
+
private config;
|
|
7
|
+
constructor(config: ComputerUseConfig);
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
listAllTools(): Promise<Tool[]>;
|
|
10
|
+
callTool(name: string, args: Record<string, unknown>): Promise<{
|
|
11
|
+
content?: Array<{
|
|
12
|
+
type: string;
|
|
13
|
+
text?: string;
|
|
14
|
+
data?: string;
|
|
15
|
+
mimeType?: string;
|
|
16
|
+
}>;
|
|
17
|
+
isError?: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
private resolveBinaryPath;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=mcp-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,EAAE,iBAAiB;IAI/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBxB,YAAY,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAgB/B,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC;QACT,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACnF,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAWI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,iBAAiB;CAmBhC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
5
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
6
|
+
const MCP_TIMEOUT_MS = 60_000;
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
export class CuaDriverClient {
|
|
9
|
+
client = null;
|
|
10
|
+
transport = null;
|
|
11
|
+
config;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
async connect() {
|
|
16
|
+
const binaryPath = await this.resolveBinaryPath();
|
|
17
|
+
const args = ['mcp', ...(this.config.extraArgs ?? [])];
|
|
18
|
+
this.transport = new StdioClientTransport({
|
|
19
|
+
command: binaryPath,
|
|
20
|
+
args,
|
|
21
|
+
stderr: 'pipe',
|
|
22
|
+
});
|
|
23
|
+
this.transport.onerror = (error) => {
|
|
24
|
+
console.error(`[pi-computer-use] cua-driver transport error: ${error.message}`);
|
|
25
|
+
};
|
|
26
|
+
this.client = new Client({ name: 'pi-computer-use', version: '0.1.0' }, { capabilities: {} });
|
|
27
|
+
await this.client.connect(this.transport);
|
|
28
|
+
}
|
|
29
|
+
async listAllTools() {
|
|
30
|
+
if (!this.client)
|
|
31
|
+
throw new Error('CuaDriverClient not connected');
|
|
32
|
+
const allTools = [];
|
|
33
|
+
let cursor;
|
|
34
|
+
do {
|
|
35
|
+
const result = await this.client.listTools(cursor ? { cursor } : undefined, {
|
|
36
|
+
timeout: MCP_TIMEOUT_MS,
|
|
37
|
+
});
|
|
38
|
+
allTools.push(...result.tools);
|
|
39
|
+
cursor = result.nextCursor;
|
|
40
|
+
} while (cursor);
|
|
41
|
+
return allTools;
|
|
42
|
+
}
|
|
43
|
+
async callTool(name, args) {
|
|
44
|
+
if (!this.client)
|
|
45
|
+
throw new Error('CuaDriverClient not connected');
|
|
46
|
+
return (await this.client.callTool({ name, arguments: args }, undefined, {
|
|
47
|
+
timeout: MCP_TIMEOUT_MS,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
async close() {
|
|
51
|
+
if (this.client) {
|
|
52
|
+
await this.client.close();
|
|
53
|
+
this.client = null;
|
|
54
|
+
}
|
|
55
|
+
this.transport = null;
|
|
56
|
+
}
|
|
57
|
+
async resolveBinaryPath() {
|
|
58
|
+
if (this.config.mode === 'path' && this.config.binaryPath) {
|
|
59
|
+
return this.config.binaryPath;
|
|
60
|
+
}
|
|
61
|
+
const platform = process.platform === 'win32' ? 'win32-x64' : `${process.platform}-${process.arch}`;
|
|
62
|
+
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
63
|
+
const binPath = path.resolve(__dirname, '..', 'bin', platform, `cua-driver${ext}`);
|
|
64
|
+
if (!existsSync(binPath)) {
|
|
65
|
+
throw new Error(`[pi-computer-use] cua-driver binary not found at ${binPath}. ` +
|
|
66
|
+
`Platform "${platform}" may not be supported, or set mode: "path" with binaryPath in config.`);
|
|
67
|
+
}
|
|
68
|
+
return binPath;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=mcp-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"}
|