shellx-ai 1.0.12 → 1.1.1
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/LICENSE +21 -0
- package/README.md +666 -0
- package/dist/automation/element-finder.d.ts +189 -0
- package/dist/automation/element-finder.js +322 -0
- package/dist/automation/element-finder.js.map +1 -0
- package/dist/automation/ui-action-handler.d.ts +330 -0
- package/dist/automation/ui-action-handler.js +873 -0
- package/dist/automation/ui-action-handler.js.map +1 -0
- package/dist/cbor-compat.d.ts +27 -0
- package/dist/cbor-compat.js +111 -0
- package/dist/cbor-compat.js.map +1 -0
- package/dist/domain-manager.d.ts +80 -0
- package/dist/domain-manager.js +161 -0
- package/dist/domain-manager.js.map +1 -0
- package/dist/error-handler.d.ts +87 -0
- package/dist/error-handler.js +151 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/errors.d.ts +114 -0
- package/dist/errors.js +139 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +163 -54
- package/dist/index.js +678 -481
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +81 -0
- package/dist/logger.js +128 -0
- package/dist/logger.js.map +1 -0
- package/dist/protocol.d.ts +147 -31
- package/dist/protocol.js +2 -2
- package/dist/protocol.js.map +1 -0
- package/dist/shell/output-buffer.d.ts +152 -0
- package/dist/shell/output-buffer.js +176 -0
- package/dist/shell/output-buffer.js.map +1 -0
- package/dist/shell/shell-command-executor.d.ts +182 -0
- package/dist/shell/shell-command-executor.js +404 -0
- package/dist/shell/shell-command-executor.js.map +1 -0
- package/dist/shellx.d.ts +681 -178
- package/dist/shellx.js +762 -1159
- package/dist/shellx.js.map +1 -0
- package/dist/types.d.ts +132 -57
- package/dist/types.js +4 -4
- package/dist/types.js.map +1 -0
- package/dist/utils/retry-helper.d.ts +73 -0
- package/dist/utils/retry-helper.js +95 -0
- package/dist/utils/retry-helper.js.map +1 -0
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +20 -23
- package/dist/utils.js.map +1 -0
- package/package.json +95 -62
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 10cl <notice@toscl.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
# ShellX AI
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**TypeScript library for Android device automation via WebSocket**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.org/package/shellx-ai)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](https://www.typescriptlang.org/)
|
|
11
|
+
|
|
12
|
+
[Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-examples)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Summary
|
|
19
|
+
|
|
20
|
+
ShellX AI is a TypeScript library that enables programmatic control of Android devices through a WebSocket connection. It provides a simple, type-safe API for:
|
|
21
|
+
|
|
22
|
+
- **UI Automation** - Click, input, swipe, press keys, wait for elements
|
|
23
|
+
- **Element Finding** - Find UI elements by text, ID, class, or coordinates
|
|
24
|
+
- **Shell Commands** - Execute shell commands and get output
|
|
25
|
+
- **Device Info** - Get screen info, app info, screenshots
|
|
26
|
+
- **Batch Operations** - Execute multiple actions in sequence
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- 🎯 **Simple API** - Intuitive methods for common automation tasks
|
|
33
|
+
- 🔄 **Auto Retry** - Built-in retry logic for robust operations
|
|
34
|
+
- 📝 **Type-Safe** - Full TypeScript support with comprehensive types
|
|
35
|
+
- 🌍 **Cross-Platform** - Works in Node.js and browser environments
|
|
36
|
+
- 📸 **Screenshots** - Capture screenshots with customizable options
|
|
37
|
+
- 🔧 **Shell Commands** - Execute commands with real-time output
|
|
38
|
+
- 🛠️ **Batch Actions** - Chain multiple operations together
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install shellx-ai
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Requirements
|
|
49
|
+
|
|
50
|
+
- Node.js >= 14.0.0
|
|
51
|
+
- TypeScript >= 4.0.0 (recommended)
|
|
52
|
+
- Android device connected to ShellX service
|
|
53
|
+
|
|
54
|
+
### Optional Dependencies
|
|
55
|
+
|
|
56
|
+
For Node.js environment, install ws:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install ws # Optional, for Node.js WebSocket support
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For browser environments, no additional dependencies needed.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
### 1. Basic Example
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { ShellX } from 'shellx-ai';
|
|
72
|
+
|
|
73
|
+
// Create ShellX instance
|
|
74
|
+
const shellx = new ShellX({
|
|
75
|
+
deviceId: 'your-device-id' // Replace with your device ID
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Wait for connection
|
|
79
|
+
await shellx.ready();
|
|
80
|
+
|
|
81
|
+
// Click element by text
|
|
82
|
+
await shellx.click('Settings');
|
|
83
|
+
|
|
84
|
+
// Get screen info
|
|
85
|
+
const screen = await shellx.getScreenInfo();
|
|
86
|
+
console.log(`Screen: ${screen.width}x${screen.height}`);
|
|
87
|
+
|
|
88
|
+
// Execute shell command
|
|
89
|
+
const result = await shellx.command('getprop ro.build.version.release');
|
|
90
|
+
console.log('Android version:', result.output);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. Using Environment Variables
|
|
94
|
+
|
|
95
|
+
Create a `.env` file:
|
|
96
|
+
|
|
97
|
+
```env
|
|
98
|
+
DEVICE_ID=your-device-id
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then use it in your code:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { ShellX } from 'shellx-ai';
|
|
105
|
+
import dotenv from 'dotenv';
|
|
106
|
+
|
|
107
|
+
dotenv.config();
|
|
108
|
+
|
|
109
|
+
const shellx = new ShellX({
|
|
110
|
+
deviceId: process.env.DEVICE_ID
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await shellx.ready();
|
|
114
|
+
// Start automating...
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 3. With Connection Events
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const shellx = new ShellX({
|
|
121
|
+
deviceId: 'your-device-id',
|
|
122
|
+
onOpen: () => console.log('✅ Connected'),
|
|
123
|
+
onClose: () => console.log('❌ Disconnected'),
|
|
124
|
+
onError: (error) => console.error('⚠️ Error:', error)
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await shellx.ready();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## API Reference
|
|
133
|
+
|
|
134
|
+
### ShellX Class
|
|
135
|
+
|
|
136
|
+
The main class for Android automation.
|
|
137
|
+
|
|
138
|
+
#### Constructor
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
new ShellX(options: ShellXOptions)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Options:**
|
|
145
|
+
|
|
146
|
+
| Parameter | Type | Required | Default | Description |
|
|
147
|
+
|-----------|------|----------|---------|-------------|
|
|
148
|
+
| `deviceId` | `string` | Yes | - | Device ID (UUID or identifier) |
|
|
149
|
+
| `timeout` | `number` | No | `5000` | Connection timeout in ms |
|
|
150
|
+
| `reconnect` | `boolean` | No | `true` | Enable auto-reconnect |
|
|
151
|
+
| `reconnectMaxAttempts` | `number` | No | `5` | Max reconnect attempts |
|
|
152
|
+
| `logLevel` | `LogLevel` | No | `INFO` | Log level (0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) |
|
|
153
|
+
| `onOpen` | `() => void` | No | - | Callback when connection opens |
|
|
154
|
+
| `onClose` | `() => void` | No | - | Callback when connection closes |
|
|
155
|
+
| `onError` | `(error?) => void` | No | - | Callback on error |
|
|
156
|
+
| `onMessage` | `(msg) => void` | No | - | Callback on message |
|
|
157
|
+
|
|
158
|
+
#### Methods
|
|
159
|
+
|
|
160
|
+
##### Connection
|
|
161
|
+
|
|
162
|
+
| Method | Description | Returns |
|
|
163
|
+
|--------|-------------|---------|
|
|
164
|
+
| `ready()` | Wait for connection to be ready | `Promise<void>` |
|
|
165
|
+
| `getClient()` | Get underlying ConnectionClient | `ConnectionClient` |
|
|
166
|
+
|
|
167
|
+
##### UI Actions
|
|
168
|
+
|
|
169
|
+
| Method | Description | Example |
|
|
170
|
+
|--------|-------------|---------|
|
|
171
|
+
| `click(selector)` | Click element | `await shellx.click('Submit')` |
|
|
172
|
+
| `input(data)` | Input text | `await shellx.input({ text: 'Hello' })` |
|
|
173
|
+
| `swipe(data)` | Swipe gesture | `await shellx.swipe({ fromX: 500, fromY: 1000, toX: 500, toY: 500 })` |
|
|
174
|
+
| `press(key)` | Press key | `await shellx.press('BACK')` |
|
|
175
|
+
| `wait(selector)` | Wait for element | `await shellx.wait('Loading')` |
|
|
176
|
+
| `find(selector)` | Find elements | `await shellx.find('Button', { multiple: true })` |
|
|
177
|
+
|
|
178
|
+
##### Device Operations
|
|
179
|
+
|
|
180
|
+
| Method | Description | Example |
|
|
181
|
+
|--------|-------------|---------|
|
|
182
|
+
| `command(cmd)` | Execute shell command | `await shellx.command('ls -la')` |
|
|
183
|
+
| `getScreenInfo()` | Get screen info | `await shellx.getScreenInfo()` |
|
|
184
|
+
| `takeScreenshot()` | Take screenshot | `await shellx.takeScreenshot({ format: 'png' })` |
|
|
185
|
+
| `getAppInfo(pkg)` | Get app info | `await shellx.getAppInfo('com.example.app')` |
|
|
186
|
+
| `getAppList()` | Get app list | `await shellx.getAppList()` |
|
|
187
|
+
| `clipboard(data)` | Clipboard operations | `await shellx.clipboard({ text: 'Hello' })` |
|
|
188
|
+
|
|
189
|
+
##### Advanced
|
|
190
|
+
|
|
191
|
+
| Method | Description | Example |
|
|
192
|
+
|--------|-------------|---------|
|
|
193
|
+
| `executeActions(actions)` | Execute multiple actions | `await shellx.executeActions([{ text: 'OK' }, { cmd: 'ls' }])` |
|
|
194
|
+
| `sendRawMessage(msg)` | Send raw WebSocket message | `await shellx.sendRawMessage({ screenInfo: {} })` |
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Type Definitions
|
|
199
|
+
|
|
200
|
+
### Click
|
|
201
|
+
|
|
202
|
+
Click on an element by text, ID, or coordinates.
|
|
203
|
+
|
|
204
|
+
**Simplified form (click by text):**
|
|
205
|
+
```typescript
|
|
206
|
+
await shellx.click('Submit');
|
|
207
|
+
await shellx.click('Submit', { clickType: 'long' });
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Full form:**
|
|
211
|
+
```typescript
|
|
212
|
+
await shellx.click({
|
|
213
|
+
text: 'Submit', // Click by text
|
|
214
|
+
elementId: 'btn123', // Or by element ID
|
|
215
|
+
resourceId: 'submit_btn', // Or by resource ID
|
|
216
|
+
x: 500, // Or by coordinates
|
|
217
|
+
y: 1000,
|
|
218
|
+
clickType: 'single', // 'single' | 'double' | 'long' | 'normal'
|
|
219
|
+
timeout: 5000
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Input
|
|
224
|
+
|
|
225
|
+
Input text into a field.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
await shellx.input({
|
|
229
|
+
elementId: 'field123',
|
|
230
|
+
text: 'Hello World',
|
|
231
|
+
clear: true, // Clear field before input
|
|
232
|
+
hideKeyboard: true // Hide keyboard after input
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Swipe
|
|
237
|
+
|
|
238
|
+
Perform swipe gesture.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
await shellx.swipe({
|
|
242
|
+
fromX: 500,
|
|
243
|
+
fromY: 1000,
|
|
244
|
+
toX: 500,
|
|
245
|
+
toY: 500,
|
|
246
|
+
duration: 800 // Duration in ms
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Press
|
|
251
|
+
|
|
252
|
+
Press hardware key.
|
|
253
|
+
|
|
254
|
+
**Simplified:**
|
|
255
|
+
```typescript
|
|
256
|
+
await shellx.press('BACK');
|
|
257
|
+
await shellx.press('HOME');
|
|
258
|
+
await shellx.press('MENU', { longPress: true });
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Full:**
|
|
262
|
+
```typescript
|
|
263
|
+
await shellx.press({
|
|
264
|
+
key: 'BACK',
|
|
265
|
+
longPress: false
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Wait
|
|
270
|
+
|
|
271
|
+
Wait for an element condition.
|
|
272
|
+
|
|
273
|
+
**Simplified:**
|
|
274
|
+
```typescript
|
|
275
|
+
await shellx.wait('Submit');
|
|
276
|
+
await shellx.wait('Loading', { timeout: 10000 });
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Full:**
|
|
280
|
+
```typescript
|
|
281
|
+
await shellx.wait({
|
|
282
|
+
text: 'Submit',
|
|
283
|
+
condition: 'visible', // 'visible' | 'gone' | 'enabled'
|
|
284
|
+
timeout: 5000
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Find
|
|
289
|
+
|
|
290
|
+
Find UI elements.
|
|
291
|
+
|
|
292
|
+
**Simplified:**
|
|
293
|
+
```typescript
|
|
294
|
+
const result = await shellx.find('Button');
|
|
295
|
+
const all = await shellx.find('Button', { multiple: true, maxResults: 10 });
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**Full:**
|
|
299
|
+
```typescript
|
|
300
|
+
const result = await shellx.find({
|
|
301
|
+
text: 'Submit',
|
|
302
|
+
multiple: false,
|
|
303
|
+
maxResults: 100,
|
|
304
|
+
pressClick: true // Auto-click after find
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Command
|
|
309
|
+
|
|
310
|
+
Execute shell command.
|
|
311
|
+
|
|
312
|
+
**Simplified:**
|
|
313
|
+
```typescript
|
|
314
|
+
const result = await shellx.command('ls -la');
|
|
315
|
+
const result = await shellx.command('ls -la', { timeout: 5000 });
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Full:**
|
|
319
|
+
```typescript
|
|
320
|
+
const result = await shellx.command({
|
|
321
|
+
cmd: 'ls -la',
|
|
322
|
+
timeout: 10000,
|
|
323
|
+
wait: 1000 // Wait after command
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Screenshot
|
|
328
|
+
|
|
329
|
+
Take screenshot.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
const screenshot = await shellx.takeScreenshot({
|
|
333
|
+
format: 'png', // 'png' | 'jpeg'
|
|
334
|
+
quality: 100, // 0-100 for JPEG
|
|
335
|
+
saveToFile: true
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Clipboard
|
|
340
|
+
|
|
341
|
+
Clipboard operations.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// Get clipboard
|
|
345
|
+
const result = await shellx.clipboard({ get: true });
|
|
346
|
+
|
|
347
|
+
// Set clipboard
|
|
348
|
+
await shellx.clipboard({ text: 'Hello' });
|
|
349
|
+
|
|
350
|
+
// Paste clipboard
|
|
351
|
+
await shellx.clipboard({ paste: true });
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### ExecuteActions (Batch)
|
|
355
|
+
|
|
356
|
+
Execute multiple actions in sequence.
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
const result = await shellx.executeActions([
|
|
360
|
+
{ text: 'Settings' }, // Click
|
|
361
|
+
{ cmd: 'ls -la' }, // Command
|
|
362
|
+
{ fromX: 500, fromY: 1000, toX: 500, toY: 500 }, // Swipe
|
|
363
|
+
{ key: 'BACK' } // Press
|
|
364
|
+
]);
|
|
365
|
+
|
|
366
|
+
console.log(`Success: ${result.successCount}/${result.results.length}`);
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Complete Working Example
|
|
372
|
+
|
|
373
|
+
Here's a complete example that you can run directly:
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// File: example.ts
|
|
377
|
+
import { ShellX } from 'shellx-ai';
|
|
378
|
+
|
|
379
|
+
async function main() {
|
|
380
|
+
// 1. Create ShellX instance
|
|
381
|
+
const shellx = new ShellX({
|
|
382
|
+
deviceId: process.env.DEVICE_ID || 'your-device-id',
|
|
383
|
+
onOpen: () => console.log('✅ Connected!')
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
// 2. Wait for connection
|
|
388
|
+
await shellx.ready();
|
|
389
|
+
console.log('📱 Connected to device');
|
|
390
|
+
|
|
391
|
+
// 3. Get screen info
|
|
392
|
+
const screen = await shellx.getScreenInfo();
|
|
393
|
+
console.log(`Screen: ${screen.width}x${screen.height}`);
|
|
394
|
+
|
|
395
|
+
// 4. Click element
|
|
396
|
+
await shellx.click('Settings');
|
|
397
|
+
console.log('✅ Clicked Settings');
|
|
398
|
+
|
|
399
|
+
// 5. Press back
|
|
400
|
+
await shellx.press('BACK');
|
|
401
|
+
console.log('✅ Pressed BACK');
|
|
402
|
+
|
|
403
|
+
// 6. Execute command
|
|
404
|
+
const result = await shellx.command('getprop ro.build.version.release');
|
|
405
|
+
console.log(`Android: ${result.output.trim()}`);
|
|
406
|
+
|
|
407
|
+
// 7. Take screenshot
|
|
408
|
+
const screenshot = await shellx.takeScreenshot({ format: 'png' });
|
|
409
|
+
console.log(`Screenshot: ${screenshot.imagePath}`);
|
|
410
|
+
|
|
411
|
+
// 8. Batch operations
|
|
412
|
+
const batch = await shellx.executeActions([
|
|
413
|
+
{ text: 'Settings' },
|
|
414
|
+
{ cmd: 'wm size' }
|
|
415
|
+
]);
|
|
416
|
+
console.log(`Batch: ${batch.successCount}/${batch.results.length} successful`);
|
|
417
|
+
|
|
418
|
+
console.log('🎉 All operations completed!');
|
|
419
|
+
} catch (error) {
|
|
420
|
+
console.error('❌ Error:', error);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
main();
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Compile and run:
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
# Install dependencies
|
|
431
|
+
npm install shellx-ai dotenv
|
|
432
|
+
|
|
433
|
+
# Create .env file
|
|
434
|
+
echo "DEVICE_ID=your-device-id" > .env
|
|
435
|
+
|
|
436
|
+
# Run with tsx
|
|
437
|
+
npx tsx example.ts
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## Response Types
|
|
443
|
+
|
|
444
|
+
All operations return a result object with the following structure:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
interface Result {
|
|
448
|
+
success: boolean; // Operation success status
|
|
449
|
+
error?: string; // Error message if failed
|
|
450
|
+
duration: number; // Operation duration in ms
|
|
451
|
+
timestamp: number; // Operation timestamp
|
|
452
|
+
// ... additional fields specific to each operation
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### CommandResult
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
{
|
|
460
|
+
success: boolean;
|
|
461
|
+
output: string; // Command output
|
|
462
|
+
error?: string;
|
|
463
|
+
exitCode?: number;
|
|
464
|
+
duration: number;
|
|
465
|
+
cmd: string;
|
|
466
|
+
timestamp: number;
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### FindResult
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
{
|
|
474
|
+
success: boolean;
|
|
475
|
+
found: boolean;
|
|
476
|
+
count: number; // Number of elements found
|
|
477
|
+
elements: Array<{
|
|
478
|
+
id: string;
|
|
479
|
+
text: string;
|
|
480
|
+
class: string;
|
|
481
|
+
left: number;
|
|
482
|
+
top: number;
|
|
483
|
+
right: number;
|
|
484
|
+
bottom: number;
|
|
485
|
+
visible: boolean;
|
|
486
|
+
clickable: boolean;
|
|
487
|
+
}>;
|
|
488
|
+
duration: number;
|
|
489
|
+
timestamp: number;
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### ScreenInfoResult
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
{
|
|
497
|
+
success: boolean;
|
|
498
|
+
width: number;
|
|
499
|
+
height: number;
|
|
500
|
+
density: number;
|
|
501
|
+
screenOn: boolean;
|
|
502
|
+
screenUnlocked: boolean;
|
|
503
|
+
foregroundApp?: string;
|
|
504
|
+
foregroundActivity?: string;
|
|
505
|
+
model?: string;
|
|
506
|
+
androidVersion?: string;
|
|
507
|
+
manufacturer?: string;
|
|
508
|
+
duration: number;
|
|
509
|
+
timestamp: number;
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## Logging
|
|
516
|
+
|
|
517
|
+
Control logging level:
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
const shellx = new ShellX({
|
|
521
|
+
deviceId: 'your-device-id',
|
|
522
|
+
logLevel: 3 // 0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// Or at runtime
|
|
526
|
+
shellx.setLogLevel(4); // Enable debug logging
|
|
527
|
+
shellx.enableDebugLogging(); // Shortcut
|
|
528
|
+
shellx.disableLogging(); // Disable all logging
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## Error Handling
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
try {
|
|
537
|
+
await shellx.click('Settings');
|
|
538
|
+
} catch (error) {
|
|
539
|
+
if (error instanceof Error) {
|
|
540
|
+
console.error('Click failed:', error.message);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// Or check result
|
|
545
|
+
const result = await shellx.click('Settings');
|
|
546
|
+
if (!result.success) {
|
|
547
|
+
console.error('Failed:', result.error);
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## Advanced Usage
|
|
554
|
+
|
|
555
|
+
### Wait for Multiple Elements
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
const result = await shellx.waitAnyElement([
|
|
559
|
+
{ text: 'OK' },
|
|
560
|
+
{ text: 'Confirm' },
|
|
561
|
+
{ text: 'Submit' }
|
|
562
|
+
], 10000);
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Scroll to Find Element
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
const element = await shellx.scrollToFindElement(
|
|
569
|
+
{ text: 'Target Item' },
|
|
570
|
+
5, // max scroll attempts
|
|
571
|
+
'down' // direction
|
|
572
|
+
);
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Find with Retry
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
const element = await shellx.findElementWithRetry(
|
|
579
|
+
{ text: 'Submit', visible: true },
|
|
580
|
+
3, // max retries
|
|
581
|
+
1000 // retry delay
|
|
582
|
+
);
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## Platform Support
|
|
588
|
+
|
|
589
|
+
### Node.js
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
npm install shellx-ai ws
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
import { ShellX } from 'shellx-ai';
|
|
597
|
+
const shellx = new ShellX({ deviceId: 'device-id' });
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Browser
|
|
601
|
+
|
|
602
|
+
```bash
|
|
603
|
+
npm install shellx-ai
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
import { ShellX } from 'shellx-ai';
|
|
608
|
+
const shellx = new ShellX({ deviceId: 'device-id' });
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## Troubleshooting
|
|
614
|
+
|
|
615
|
+
### Connection Issues
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
const shellx = new ShellX({
|
|
619
|
+
deviceId: 'your-device-id',
|
|
620
|
+
timeout: 10000, // Increase timeout
|
|
621
|
+
reconnect: true, // Enable auto-reconnect
|
|
622
|
+
reconnectMaxAttempts: 10, // More attempts
|
|
623
|
+
onError: (error) => console.error('Connection error:', error)
|
|
624
|
+
});
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
### Element Not Found
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
// Wait for element first
|
|
631
|
+
await shellx.wait('Submit', { timeout: 10000 });
|
|
632
|
+
|
|
633
|
+
// Then click
|
|
634
|
+
await shellx.click('Submit');
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Command Timeout
|
|
638
|
+
|
|
639
|
+
```typescript
|
|
640
|
+
const result = await shellx.command({
|
|
641
|
+
cmd: 'long-running-command',
|
|
642
|
+
timeout: 30000 // 30 seconds
|
|
643
|
+
});
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## See Also
|
|
649
|
+
|
|
650
|
+
- [API-GUIDE.md](./API-GUIDE.md) - Detailed API guide
|
|
651
|
+
- [API-QUICK-REFERENCE.md](./API-QUICK-REFERENCE.md) - Quick reference
|
|
652
|
+
- [example/](./example/) - Complete working examples
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## License
|
|
657
|
+
|
|
658
|
+
MIT License - see [LICENSE](LICENSE) file.
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Support
|
|
663
|
+
|
|
664
|
+
- 📚 [Documentation](https://github.com/10cl/shellx)
|
|
665
|
+
- 🐛 [Issues](https://github.com/10cl/shellx/issues)
|
|
666
|
+
- 💬 [Discussions](https://github.com/10cl/shellx/discussions)
|