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/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 {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });