shellx-ai 1.0.0
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 +335 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.js +14 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +398 -0
- package/dist/protocol.d.ts +319 -0
- package/dist/protocol.js +2 -0
- package/dist/shellx.d.ts +175 -0
- package/dist/shellx.js +866 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +37 -0
- package/package.json +61 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createShellXWithShellMonitoring = exports.createShellX = exports.ShellX = exports.WebSocketTaskClient = void 0;
|
|
13
|
+
const uuid_1 = require("uuid");
|
|
14
|
+
const constants_1 = require("./constants");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
const cbor_x_1 = require("cbor-x");
|
|
17
|
+
/**
|
|
18
|
+
* Enhanced WebSocket Task Client with protocol-aware task methods
|
|
19
|
+
*/
|
|
20
|
+
class WebSocketTaskClient {
|
|
21
|
+
constructor(wsUrl, config = {}) {
|
|
22
|
+
this.ws = null;
|
|
23
|
+
this.connected = false;
|
|
24
|
+
this.pendingTasks = new Map();
|
|
25
|
+
this.messageQueue = [];
|
|
26
|
+
this.reconnectAttempts = 0;
|
|
27
|
+
this.pingIntervalId = null;
|
|
28
|
+
this.wsUrl = wsUrl;
|
|
29
|
+
this.config = Object.assign(Object.assign({}, constants_1.DEFAULT_CONFIG), config);
|
|
30
|
+
this.init();
|
|
31
|
+
}
|
|
32
|
+
init() {
|
|
33
|
+
console.log('Initializing WebSocket client...');
|
|
34
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
35
|
+
this.ws.binaryType = 'arraybuffer';
|
|
36
|
+
this.ws.onopen = () => {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
console.log('Connected to WebSocket server');
|
|
39
|
+
this.connected = true;
|
|
40
|
+
this.reconnectAttempts = 0;
|
|
41
|
+
(_b = (_a = this.config).onOpen) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
42
|
+
this.flushQueue();
|
|
43
|
+
this.startPing();
|
|
44
|
+
};
|
|
45
|
+
this.ws.onmessage = (event) => {
|
|
46
|
+
this.handleMessage(event);
|
|
47
|
+
};
|
|
48
|
+
this.ws.onclose = (event) => {
|
|
49
|
+
var _a, _b;
|
|
50
|
+
this.connected = false;
|
|
51
|
+
(_b = (_a = this.config).onClose) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
|
52
|
+
this.stopPing();
|
|
53
|
+
this.reconnect();
|
|
54
|
+
};
|
|
55
|
+
this.ws.onerror = (error) => {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
(_b = (_a = this.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, error);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
handleMessage(event) {
|
|
61
|
+
let serverMessage;
|
|
62
|
+
try {
|
|
63
|
+
// Handle CBOR decoding
|
|
64
|
+
let binaryData;
|
|
65
|
+
if (event.data instanceof ArrayBuffer) {
|
|
66
|
+
binaryData = new Uint8Array(event.data);
|
|
67
|
+
}
|
|
68
|
+
else if (event.data instanceof Uint8Array) {
|
|
69
|
+
binaryData = event.data;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// JSON fallback
|
|
73
|
+
serverMessage = JSON.parse(event.data);
|
|
74
|
+
this.processServerMessage(serverMessage);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
serverMessage = (0, cbor_x_1.decode)(binaryData);
|
|
78
|
+
this.processServerMessage(serverMessage);
|
|
79
|
+
}
|
|
80
|
+
catch (cborError) {
|
|
81
|
+
console.log('CBOR decode failed, trying JSON fallback:', cborError);
|
|
82
|
+
try {
|
|
83
|
+
let textData;
|
|
84
|
+
if (event.data instanceof ArrayBuffer) {
|
|
85
|
+
textData = new TextDecoder().decode(event.data);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
textData = event.data;
|
|
89
|
+
}
|
|
90
|
+
serverMessage = JSON.parse(textData);
|
|
91
|
+
this.processServerMessage(serverMessage);
|
|
92
|
+
}
|
|
93
|
+
catch (jsonError) {
|
|
94
|
+
console.error('Failed to parse message:', { cborError, jsonError });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
processServerMessage(message) {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
console.log('Received server message:', message);
|
|
101
|
+
// Call user-defined message handler
|
|
102
|
+
(_b = (_a = this.config).onMessage) === null || _b === void 0 ? void 0 : _b.call(_a, message);
|
|
103
|
+
// Handle specific message types and resolve pending tasks
|
|
104
|
+
if (message.jsonData) {
|
|
105
|
+
this.handleJsonDataResponse(message.jsonData);
|
|
106
|
+
}
|
|
107
|
+
// Handle other server message types (hello, users, shells, etc.)
|
|
108
|
+
if (message.hello !== undefined) {
|
|
109
|
+
console.log('Server hello, user ID:', message.hello);
|
|
110
|
+
}
|
|
111
|
+
if (message.pong !== undefined) {
|
|
112
|
+
console.log('Received pong:', message.pong);
|
|
113
|
+
}
|
|
114
|
+
if (message.error) {
|
|
115
|
+
console.error('Server error:', message.error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
handleJsonDataResponse(jsonData) {
|
|
119
|
+
// Match responses to pending tasks based on response type
|
|
120
|
+
for (const [taskId, task] of this.pendingTasks.entries()) {
|
|
121
|
+
let responseData = null;
|
|
122
|
+
let shouldResolve = false;
|
|
123
|
+
switch (task.type) {
|
|
124
|
+
case 'findElement':
|
|
125
|
+
if (jsonData.findElement) {
|
|
126
|
+
responseData = jsonData.findElement;
|
|
127
|
+
shouldResolve = true;
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
case 'waitElement':
|
|
131
|
+
if (jsonData.waitElement) {
|
|
132
|
+
responseData = jsonData.waitElement;
|
|
133
|
+
shouldResolve = true;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
case 'screenShot':
|
|
137
|
+
if (jsonData.screenShot) {
|
|
138
|
+
responseData = jsonData.screenShot;
|
|
139
|
+
shouldResolve = true;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
case 'screenInfo':
|
|
143
|
+
if (jsonData.screenInfo) {
|
|
144
|
+
responseData = jsonData.screenInfo;
|
|
145
|
+
shouldResolve = true;
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
case 'appList':
|
|
149
|
+
if (jsonData.appList) {
|
|
150
|
+
responseData = jsonData.appList;
|
|
151
|
+
shouldResolve = true;
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
case 'action':
|
|
155
|
+
if (jsonData.action_event) {
|
|
156
|
+
responseData = jsonData.action_event;
|
|
157
|
+
shouldResolve = true;
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
if (shouldResolve) {
|
|
162
|
+
clearTimeout(task.timer);
|
|
163
|
+
this.pendingTasks.delete(taskId);
|
|
164
|
+
if ((responseData === null || responseData === void 0 ? void 0 : responseData.success) === false) {
|
|
165
|
+
task.reject(new Error(responseData.errorMessage || 'Task failed'));
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
task.resolve(responseData);
|
|
169
|
+
}
|
|
170
|
+
break; // Only resolve the first matching task
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
sendMessage(message, taskType) {
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
const taskId = (0, uuid_1.v4)();
|
|
177
|
+
if (taskType) {
|
|
178
|
+
const timer = setTimeout(() => {
|
|
179
|
+
this.pendingTasks.delete(taskId);
|
|
180
|
+
reject(new Error(`Task ${taskType} timeout (${this.config.timeout}ms)`));
|
|
181
|
+
}, this.config.timeout);
|
|
182
|
+
this.pendingTasks.set(taskId, { resolve, reject, timer, type: taskType });
|
|
183
|
+
}
|
|
184
|
+
if (this.connected && this.ws) {
|
|
185
|
+
try {
|
|
186
|
+
console.log('Sending message:', message);
|
|
187
|
+
this.ws.send((0, cbor_x_1.encode)(message));
|
|
188
|
+
if (!taskType)
|
|
189
|
+
resolve(undefined); // For fire-and-forget messages
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
if (taskType) {
|
|
193
|
+
this.pendingTasks.delete(taskId);
|
|
194
|
+
}
|
|
195
|
+
reject(error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this.messageQueue.push(message);
|
|
200
|
+
if (!taskType)
|
|
201
|
+
resolve(undefined);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
// ===== PROTOCOL-AWARE TASK METHODS =====
|
|
206
|
+
/**
|
|
207
|
+
* Find UI elements on the screen
|
|
208
|
+
*/
|
|
209
|
+
findElement(selector, options) {
|
|
210
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
211
|
+
const findAction = {
|
|
212
|
+
type: 'find',
|
|
213
|
+
selector,
|
|
214
|
+
options
|
|
215
|
+
};
|
|
216
|
+
return this.sendMessage({ findElement: findAction }, 'findElement');
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Wait for UI element to appear
|
|
221
|
+
*/
|
|
222
|
+
waitElement(selector, options) {
|
|
223
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
224
|
+
const waitAction = {
|
|
225
|
+
type: 'wait',
|
|
226
|
+
selector,
|
|
227
|
+
options
|
|
228
|
+
};
|
|
229
|
+
return this.sendMessage({ waitElement: waitAction }, 'waitElement');
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Take a screenshot
|
|
234
|
+
*/
|
|
235
|
+
screenShot(options) {
|
|
236
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
237
|
+
return this.sendMessage({ screenShot: options || { format: 'png' } }, 'screenShot');
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get screen information
|
|
242
|
+
*/
|
|
243
|
+
getScreenInfo() {
|
|
244
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
245
|
+
return this.sendMessage({ screenInfo: {} }, 'screenInfo');
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get list of installed apps
|
|
250
|
+
*/
|
|
251
|
+
getAppList(options) {
|
|
252
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
253
|
+
return this.sendMessage({ appList: options || {} }, 'appList');
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get specific app information
|
|
258
|
+
*/
|
|
259
|
+
getAppInfo(packageName) {
|
|
260
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
261
|
+
return this.sendMessage({ appInfo: { packageName } }, 'appInfo');
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Execute an action sequence
|
|
266
|
+
*/
|
|
267
|
+
executeAction(actionSequence) {
|
|
268
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
+
return this.sendMessage({ actions: actionSequence }, 'action');
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Execute promptflow actions
|
|
274
|
+
*/
|
|
275
|
+
executePromptFlow(actionSequence) {
|
|
276
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
277
|
+
return this.sendMessage({ promptflowx: actionSequence });
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Listen for display changes
|
|
282
|
+
*/
|
|
283
|
+
screenChange(options) {
|
|
284
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
return this.sendMessage({
|
|
286
|
+
screenChange: options || { enable: true }
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Switch to a different node
|
|
292
|
+
*/
|
|
293
|
+
switchNode(nodeId) {
|
|
294
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
295
|
+
return this.sendMessage({ switchNode: nodeId });
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Send authentication data
|
|
300
|
+
*/
|
|
301
|
+
authenticate(authData) {
|
|
302
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
303
|
+
return this.sendMessage({ authenticate: authData });
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Set user name
|
|
308
|
+
*/
|
|
309
|
+
setName(name) {
|
|
310
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
311
|
+
return this.sendMessage({ setName: name });
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Send chat message
|
|
316
|
+
*/
|
|
317
|
+
sendChat(message) {
|
|
318
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
319
|
+
return this.sendMessage({ chat: message });
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Send raw message (for custom integrations)
|
|
324
|
+
*/
|
|
325
|
+
sendRawMessage(message) {
|
|
326
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
327
|
+
return this.sendMessage(message);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
// ===== CONNECTION MANAGEMENT =====
|
|
331
|
+
startPing() {
|
|
332
|
+
this.stopPing();
|
|
333
|
+
console.log('Starting ping...');
|
|
334
|
+
this.pingIntervalId = setInterval(() => {
|
|
335
|
+
if (this.ws && this.connected) {
|
|
336
|
+
this.ws.send((0, cbor_x_1.encode)({ ping: BigInt(Date.now()) }));
|
|
337
|
+
}
|
|
338
|
+
}, this.config.pingInterval);
|
|
339
|
+
}
|
|
340
|
+
stopPing() {
|
|
341
|
+
if (this.pingIntervalId !== null) {
|
|
342
|
+
clearInterval(this.pingIntervalId);
|
|
343
|
+
this.pingIntervalId = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
reconnect() {
|
|
347
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
348
|
+
var _a, _b;
|
|
349
|
+
if (this.reconnectAttempts >= this.config.reconnectMaxAttempts) {
|
|
350
|
+
(_b = (_a = this.config).onReconnectFailed) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
this.reconnectAttempts++;
|
|
354
|
+
yield (0, utils_1.wait)(this.config.reconnectInterval * this.reconnectAttempts);
|
|
355
|
+
this.init();
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
flushQueue() {
|
|
359
|
+
while (this.messageQueue.length > 0 && this.ws) {
|
|
360
|
+
const message = this.messageQueue.shift();
|
|
361
|
+
if (message) {
|
|
362
|
+
try {
|
|
363
|
+
console.log('flushQueue Sending message:', message);
|
|
364
|
+
this.ws.send((0, cbor_x_1.encode)(message));
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.error('Failed to send queued message:', error);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
close() {
|
|
373
|
+
var _a;
|
|
374
|
+
this.connected = false;
|
|
375
|
+
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
|
|
376
|
+
this.pendingTasks.clear();
|
|
377
|
+
this.messageQueue = [];
|
|
378
|
+
this.stopPing();
|
|
379
|
+
}
|
|
380
|
+
// Getters for debugging/monitoring
|
|
381
|
+
get isConnected() {
|
|
382
|
+
return this.connected;
|
|
383
|
+
}
|
|
384
|
+
get pendingTaskCount() {
|
|
385
|
+
return this.pendingTasks.size;
|
|
386
|
+
}
|
|
387
|
+
get queuedMessageCount() {
|
|
388
|
+
return this.messageQueue.length;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
exports.WebSocketTaskClient = WebSocketTaskClient;
|
|
392
|
+
exports.default = WebSocketTaskClient;
|
|
393
|
+
// Export ShellX automation utilities
|
|
394
|
+
var shellx_1 = require("./shellx");
|
|
395
|
+
Object.defineProperty(exports, "ShellX", { enumerable: true, get: function () { return shellx_1.ShellX; } });
|
|
396
|
+
Object.defineProperty(exports, "createShellX", { enumerable: true, get: function () { return shellx_1.createShellX; } });
|
|
397
|
+
Object.defineProperty(exports, "createShellXWithShellMonitoring", { enumerable: true, get: function () { return shellx_1.createShellXWithShellMonitoring; } });
|
|
398
|
+
// PromptFlow 模块已移至 examples/ 目录作为示例实现
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
type Sid = number;
|
|
2
|
+
type Uid = number;
|
|
3
|
+
/** UI Element bounds */
|
|
4
|
+
export type UIBounds = {
|
|
5
|
+
left: number;
|
|
6
|
+
top: number;
|
|
7
|
+
right: number;
|
|
8
|
+
bottom: number;
|
|
9
|
+
};
|
|
10
|
+
/** UI Element information */
|
|
11
|
+
export type UIElement = {
|
|
12
|
+
elementId: string;
|
|
13
|
+
className: string;
|
|
14
|
+
resourceId: string;
|
|
15
|
+
text: string;
|
|
16
|
+
describe: string;
|
|
17
|
+
bounds: UIBounds;
|
|
18
|
+
visible: boolean;
|
|
19
|
+
clickable: boolean;
|
|
20
|
+
};
|
|
21
|
+
/** UI Hierarchy information */
|
|
22
|
+
export type UIHierarchy = {
|
|
23
|
+
elements: UIElement[];
|
|
24
|
+
timestamp: number;
|
|
25
|
+
found: boolean;
|
|
26
|
+
totalMatches?: number;
|
|
27
|
+
success?: boolean;
|
|
28
|
+
errorMessage?: string;
|
|
29
|
+
};
|
|
30
|
+
export type WAITElement = {
|
|
31
|
+
element: UIElement;
|
|
32
|
+
timestamp: bigint;
|
|
33
|
+
elapsedTimeMs: boolean;
|
|
34
|
+
success?: boolean;
|
|
35
|
+
errorMessage?: string;
|
|
36
|
+
};
|
|
37
|
+
/** Screen capture response */
|
|
38
|
+
export type ScreenShotResponse = {
|
|
39
|
+
imageData: string;
|
|
40
|
+
format: 'png' | 'jpeg';
|
|
41
|
+
timestamp: bigint;
|
|
42
|
+
dimensions: ScreenDimensions;
|
|
43
|
+
success?: boolean;
|
|
44
|
+
errorMessage?: string;
|
|
45
|
+
};
|
|
46
|
+
export type ScreenInfoResponse = {
|
|
47
|
+
displayId?: number;
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
density?: number;
|
|
51
|
+
name?: string;
|
|
52
|
+
visible?: boolean;
|
|
53
|
+
foregroundPackageName?: string;
|
|
54
|
+
foregroundActivityName?: string;
|
|
55
|
+
screenOn?: boolean;
|
|
56
|
+
screenUnlocked?: boolean;
|
|
57
|
+
accurateForegroundActivity?: string;
|
|
58
|
+
accurateForegroundApp?: string;
|
|
59
|
+
timestamp: bigint;
|
|
60
|
+
success?: boolean;
|
|
61
|
+
errorMessage?: string;
|
|
62
|
+
};
|
|
63
|
+
export type App = {
|
|
64
|
+
packageName: string;
|
|
65
|
+
appName: string;
|
|
66
|
+
versionName: string;
|
|
67
|
+
versionCode: number;
|
|
68
|
+
isSystemApp: boolean;
|
|
69
|
+
isEnabled: boolean;
|
|
70
|
+
firstInstallTime: number;
|
|
71
|
+
lastUpdateTime: number;
|
|
72
|
+
sourceDir: string;
|
|
73
|
+
};
|
|
74
|
+
export type AppListResponse = {
|
|
75
|
+
apps: App[];
|
|
76
|
+
totalCount: number;
|
|
77
|
+
systemAppCount: number;
|
|
78
|
+
userAppCount: number;
|
|
79
|
+
timestamp: bigint;
|
|
80
|
+
success?: boolean;
|
|
81
|
+
errorMessage?: string;
|
|
82
|
+
};
|
|
83
|
+
/** Screen change event response */
|
|
84
|
+
export type ScreenChangeEvent = {
|
|
85
|
+
eventType: 'SCREEN_CHANGED';
|
|
86
|
+
timestamp: bigint;
|
|
87
|
+
changeRatio: number;
|
|
88
|
+
imageData?: string;
|
|
89
|
+
};
|
|
90
|
+
export interface ActionSequence {
|
|
91
|
+
title?: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
actions: Array<ShellCommandAction | ClickAction | InputAction | SwipeAction | KeyAction | WaitAction | findAction | getAppInfoAction | completeAction>;
|
|
94
|
+
options?: {
|
|
95
|
+
continueOnError?: boolean;
|
|
96
|
+
timeoutMs?: number;
|
|
97
|
+
};
|
|
98
|
+
deleted?: boolean;
|
|
99
|
+
}
|
|
100
|
+
export type JSONData = {
|
|
101
|
+
findElement?: UIHierarchy;
|
|
102
|
+
waitElement?: WAITElement;
|
|
103
|
+
screenShot?: ScreenShotResponse;
|
|
104
|
+
screenInfo?: ScreenInfoResponse;
|
|
105
|
+
screenChange?: ScreenChangeEvent;
|
|
106
|
+
appList?: AppListResponse;
|
|
107
|
+
promptflowx?: ActionSequence[];
|
|
108
|
+
action_event?: ClickAction | KeyAction | SwipeAction;
|
|
109
|
+
};
|
|
110
|
+
/** Position and size of a window, see the Rust version. */
|
|
111
|
+
export type WsWinsize = {
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
rows: number;
|
|
115
|
+
cols: number;
|
|
116
|
+
mode?: number;
|
|
117
|
+
};
|
|
118
|
+
/** Information about a user, see the Rust version */
|
|
119
|
+
export type WsUser = {
|
|
120
|
+
name: string;
|
|
121
|
+
cursor: [number, number] | null;
|
|
122
|
+
focus: number | null;
|
|
123
|
+
};
|
|
124
|
+
/** Screen capture dimensions */
|
|
125
|
+
export type ScreenDimensions = {
|
|
126
|
+
width: number;
|
|
127
|
+
height: number;
|
|
128
|
+
};
|
|
129
|
+
/** Server message type, see the Rust version. */
|
|
130
|
+
export type WsServer = {
|
|
131
|
+
input?: string;
|
|
132
|
+
hello?: Uid;
|
|
133
|
+
invalidAuth?: [];
|
|
134
|
+
users?: [Uid, WsUser][];
|
|
135
|
+
userDiff?: [Uid, WsUser | null];
|
|
136
|
+
shells?: [Sid, WsWinsize][];
|
|
137
|
+
chunks?: [Sid, number, Uint8Array[]];
|
|
138
|
+
hear?: [Uid, string, string];
|
|
139
|
+
shellLatency?: number | bigint;
|
|
140
|
+
pong?: number | bigint;
|
|
141
|
+
error?: string;
|
|
142
|
+
jsonData?: JSONData;
|
|
143
|
+
uiClick?: [string, number, number];
|
|
144
|
+
uiRefresh?: boolean;
|
|
145
|
+
};
|
|
146
|
+
/** Screen capture region */
|
|
147
|
+
export type ScreenRegion = {
|
|
148
|
+
left: number;
|
|
149
|
+
top: number;
|
|
150
|
+
width: number;
|
|
151
|
+
height: number;
|
|
152
|
+
};
|
|
153
|
+
/** Screen capture options */
|
|
154
|
+
export type ScreenShotOptions = {
|
|
155
|
+
format: 'png' | 'jpeg';
|
|
156
|
+
quality?: number;
|
|
157
|
+
scale?: number;
|
|
158
|
+
region?: ScreenRegion;
|
|
159
|
+
};
|
|
160
|
+
/** Client message type, see the Rust version. */
|
|
161
|
+
export type WsClient = {
|
|
162
|
+
authenticate?: Uint8Array;
|
|
163
|
+
setName?: string;
|
|
164
|
+
setCursor?: [number, number] | null;
|
|
165
|
+
setFocus?: number | null;
|
|
166
|
+
create?: [number, number];
|
|
167
|
+
close?: Sid;
|
|
168
|
+
move?: [Sid, WsWinsize | null];
|
|
169
|
+
data?: [Sid, Uint8Array, bigint];
|
|
170
|
+
subscribe?: [Sid, number];
|
|
171
|
+
chat?: string;
|
|
172
|
+
ping?: bigint;
|
|
173
|
+
findElement?: findAction;
|
|
174
|
+
waitElement?: WaitAction;
|
|
175
|
+
screenShot?: ScreenShotOptions;
|
|
176
|
+
screenInfo?: {};
|
|
177
|
+
screenChange?: {
|
|
178
|
+
interval?: number;
|
|
179
|
+
compareThreshold?: number;
|
|
180
|
+
includeScreenshot?: boolean;
|
|
181
|
+
enable?: boolean;
|
|
182
|
+
};
|
|
183
|
+
action?: ShellXActions;
|
|
184
|
+
actions?: ActionSequence;
|
|
185
|
+
appInfo?: {
|
|
186
|
+
packageName: string;
|
|
187
|
+
};
|
|
188
|
+
appList?: {
|
|
189
|
+
includeSystemApps?: boolean;
|
|
190
|
+
includeDisabledApps?: boolean;
|
|
191
|
+
};
|
|
192
|
+
promptflowx?: ActionSequence;
|
|
193
|
+
switchNode?: string;
|
|
194
|
+
};
|
|
195
|
+
export type ShellXActions = {
|
|
196
|
+
title?: string;
|
|
197
|
+
thought?: string;
|
|
198
|
+
action: ShellCommandAction | ClickAction | InputAction | SwipeAction | KeyAction | WaitAction | findAction | getAppInfoAction | completeAction;
|
|
199
|
+
};
|
|
200
|
+
interface ShellCommandAction {
|
|
201
|
+
title?: string;
|
|
202
|
+
type: "command";
|
|
203
|
+
command: string;
|
|
204
|
+
}
|
|
205
|
+
interface getAppInfoAction {
|
|
206
|
+
title?: string;
|
|
207
|
+
type: "get_app_info";
|
|
208
|
+
packageName: string;
|
|
209
|
+
}
|
|
210
|
+
interface ClickAction {
|
|
211
|
+
title?: string;
|
|
212
|
+
type: 'click';
|
|
213
|
+
target: {
|
|
214
|
+
type: "elementId";
|
|
215
|
+
value: string;
|
|
216
|
+
} | {
|
|
217
|
+
type: "resourceId";
|
|
218
|
+
value: string;
|
|
219
|
+
} | {
|
|
220
|
+
type: "coordinate";
|
|
221
|
+
value: {
|
|
222
|
+
"x": number;
|
|
223
|
+
"y": number;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
options?: {
|
|
227
|
+
timeoutMs?: number;
|
|
228
|
+
durationMs?: number;
|
|
229
|
+
waitAfterMs?: number;
|
|
230
|
+
clickType?: 'normal' | 'long' | 'double';
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
interface InputAction {
|
|
234
|
+
title?: string;
|
|
235
|
+
type: "input";
|
|
236
|
+
text: string;
|
|
237
|
+
target: {
|
|
238
|
+
type?: "elementId";
|
|
239
|
+
value?: string;
|
|
240
|
+
} | {
|
|
241
|
+
type: "resourceId";
|
|
242
|
+
value: string;
|
|
243
|
+
};
|
|
244
|
+
options?: {
|
|
245
|
+
waitAfterMs?: number;
|
|
246
|
+
replaceExisting?: boolean;
|
|
247
|
+
hideKeyboardAfter?: boolean;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
interface SwipeAction {
|
|
251
|
+
title?: string;
|
|
252
|
+
type: 'swipe';
|
|
253
|
+
"from": {
|
|
254
|
+
"x": number;
|
|
255
|
+
"y": number;
|
|
256
|
+
};
|
|
257
|
+
"to": {
|
|
258
|
+
"x": number;
|
|
259
|
+
"y": number;
|
|
260
|
+
};
|
|
261
|
+
options?: {
|
|
262
|
+
durationMs?: number;
|
|
263
|
+
steps?: number;
|
|
264
|
+
inertia?: boolean;
|
|
265
|
+
waitAfterMs?: number;
|
|
266
|
+
replaceExisting?: boolean;
|
|
267
|
+
hideKeyboardAfter?: boolean;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
interface KeyAction {
|
|
271
|
+
title?: string;
|
|
272
|
+
type: "key";
|
|
273
|
+
keyCode?: string;
|
|
274
|
+
options?: {
|
|
275
|
+
longPress?: boolean;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
export interface WaitAction {
|
|
279
|
+
title?: string;
|
|
280
|
+
type?: "wait";
|
|
281
|
+
selector: ElementSelector;
|
|
282
|
+
options?: WaitOptions;
|
|
283
|
+
condition?: string;
|
|
284
|
+
}
|
|
285
|
+
export interface findAction {
|
|
286
|
+
title?: string;
|
|
287
|
+
type?: "find";
|
|
288
|
+
selector: ElementSelector;
|
|
289
|
+
options?: FindOptions;
|
|
290
|
+
}
|
|
291
|
+
export type completeAction = {
|
|
292
|
+
title?: string;
|
|
293
|
+
type: "complete";
|
|
294
|
+
result?: string;
|
|
295
|
+
};
|
|
296
|
+
export type ElementSelector = {
|
|
297
|
+
elementId?: string;
|
|
298
|
+
className?: string;
|
|
299
|
+
resourceId?: string;
|
|
300
|
+
text?: string;
|
|
301
|
+
textContains?: string;
|
|
302
|
+
textMatches?: string;
|
|
303
|
+
visible?: boolean;
|
|
304
|
+
clickable?: boolean;
|
|
305
|
+
};
|
|
306
|
+
export type WaitOptions = {
|
|
307
|
+
timeoutMs?: number;
|
|
308
|
+
intervalMs?: number;
|
|
309
|
+
failOnTimeout?: boolean;
|
|
310
|
+
};
|
|
311
|
+
export type FindOptions = {
|
|
312
|
+
timeout?: number;
|
|
313
|
+
visibleOnly?: boolean;
|
|
314
|
+
clickableOnly?: boolean;
|
|
315
|
+
multiple?: boolean;
|
|
316
|
+
waitForVisible?: boolean;
|
|
317
|
+
maxResults?: number;
|
|
318
|
+
};
|
|
319
|
+
export {};
|
package/dist/protocol.js
ADDED