askui 0.18.0 → 0.19.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/cjs/core/ai-element/ai-element-collection.d.ts +10 -0
- package/dist/cjs/core/ai-element/ai-element-collection.js +78 -0
- package/dist/cjs/core/ai-element/ai-element-error.d.ts +2 -0
- package/dist/cjs/core/ai-element/ai-element-error.js +6 -0
- package/dist/cjs/core/ai-element/ai-element.d.ts +27 -0
- package/dist/cjs/core/ai-element/ai-element.js +31 -0
- package/dist/cjs/core/model/custom-element-json.d.ts +32 -15
- package/dist/cjs/core/model/custom-element.d.ts +3 -2
- package/dist/cjs/core/model/custom-element.js +4 -2
- package/dist/cjs/core/reporting/step-reporter.js +15 -6
- package/dist/cjs/execution/dsl.d.ts +488 -113
- package/dist/cjs/execution/dsl.js +519 -113
- package/dist/cjs/execution/index.d.ts +1 -1
- package/dist/cjs/execution/index.js +11 -3
- package/dist/cjs/execution/inference-client.js +9 -4
- package/dist/cjs/execution/ui-control-client-dependency-builder.d.ts +1 -0
- package/dist/cjs/execution/ui-control-client-dependency-builder.js +6 -3
- package/dist/cjs/execution/ui-control-client.d.ts +101 -16
- package/dist/cjs/execution/ui-control-client.js +142 -52
- package/dist/cjs/execution/ui-controller-client-interface.d.ts +2 -0
- package/dist/cjs/execution/ui-controller-client.d.ts +1 -0
- package/dist/cjs/execution/ui-controller-client.js +11 -1
- package/dist/cjs/execution/ui-controller-not-connected-error.d.ts +4 -0
- package/dist/cjs/execution/ui-controller-not-connected-error.js +12 -0
- package/dist/cjs/main.d.ts +1 -1
- package/dist/cjs/main.js +12 -3
- package/dist/cjs/utils/analytics/analytics.d.ts +3 -1
- package/dist/cjs/utils/analytics/analytics.js +5 -0
- package/dist/cjs/utils/http/custom-errors/index.js +1 -1
- package/dist/cjs/utils/http/http-client-got.js +46 -20
- package/dist/esm/core/ai-element/ai-element-collection.d.ts +10 -0
- package/dist/esm/core/ai-element/ai-element-collection.js +71 -0
- package/dist/esm/core/ai-element/ai-element-error.d.ts +2 -0
- package/dist/esm/core/ai-element/ai-element-error.js +2 -0
- package/dist/esm/core/ai-element/ai-element.d.ts +27 -0
- package/dist/esm/core/ai-element/ai-element.js +28 -0
- package/dist/esm/core/model/custom-element-json.d.ts +32 -15
- package/dist/esm/core/model/custom-element.d.ts +3 -2
- package/dist/esm/core/model/custom-element.js +4 -2
- package/dist/esm/core/reporting/step-reporter.js +15 -6
- package/dist/esm/execution/dsl.d.ts +488 -113
- package/dist/esm/execution/dsl.js +519 -113
- package/dist/esm/execution/index.d.ts +1 -1
- package/dist/esm/execution/index.js +1 -1
- package/dist/esm/execution/inference-client.js +9 -4
- package/dist/esm/execution/ui-control-client-dependency-builder.d.ts +1 -0
- package/dist/esm/execution/ui-control-client-dependency-builder.js +6 -3
- package/dist/esm/execution/ui-control-client.d.ts +101 -16
- package/dist/esm/execution/ui-control-client.js +142 -49
- package/dist/esm/execution/ui-controller-client-interface.d.ts +2 -0
- package/dist/esm/execution/ui-controller-client.d.ts +1 -0
- package/dist/esm/execution/ui-controller-client.js +11 -1
- package/dist/esm/execution/ui-controller-not-connected-error.d.ts +4 -0
- package/dist/esm/execution/ui-controller-not-connected-error.js +8 -0
- package/dist/esm/main.d.ts +1 -1
- package/dist/esm/main.js +1 -1
- package/dist/esm/utils/analytics/analytics.d.ts +3 -1
- package/dist/esm/utils/analytics/analytics.js +5 -0
- package/dist/esm/utils/http/custom-errors/index.js +1 -1
- package/dist/esm/utils/http/http-client-got.js +46 -20
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './ui-control-client';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './ui-control-client';
|
|
@@ -56,12 +56,17 @@ export class InferenceClient {
|
|
|
56
56
|
inference(customElements = [], image, instruction) {
|
|
57
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
58
58
|
const resizedImage = yield this.resizeIfNeeded(customElements, image);
|
|
59
|
-
const response = yield this.httpClient.post(this.urls.inference, {
|
|
60
|
-
customElements,
|
|
59
|
+
const response = yield this.httpClient.post(this.urls.inference, this.urls.inference.includes('v4-experimental') ? {
|
|
61
60
|
image: resizedImage.base64Image,
|
|
62
61
|
instruction,
|
|
63
|
-
|
|
64
|
-
}
|
|
62
|
+
tasks: ['OCR'],
|
|
63
|
+
}
|
|
64
|
+
: {
|
|
65
|
+
customElements,
|
|
66
|
+
image: resizedImage.base64Image,
|
|
67
|
+
instruction,
|
|
68
|
+
modelComposition: this.modelComposition,
|
|
69
|
+
});
|
|
65
70
|
InferenceClient.logMetaInformation(response);
|
|
66
71
|
return InferenceResponse.fromJson(response.body, resizedImage.resizeRatio, image);
|
|
67
72
|
});
|
|
@@ -8,6 +8,7 @@ export declare class UiControlClientDependencyBuilder {
|
|
|
8
8
|
static build(clientArgs: ClientArgsWithDefaults): Promise<{
|
|
9
9
|
executionRuntime: ExecutionRuntime;
|
|
10
10
|
stepReporter: StepReporter;
|
|
11
|
+
workspaceId: string | undefined;
|
|
11
12
|
}>;
|
|
12
13
|
static getClientArgsWithDefaults(clientArgs: ClientArgs): Promise<ClientArgsWithDefaults>;
|
|
13
14
|
}
|
|
@@ -30,29 +30,32 @@ export class UiControlClientDependencyBuilder {
|
|
|
30
30
|
var _a;
|
|
31
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
32
|
const httpClient = yield UiControlClientDependencyBuilder.buildHttpClient(clientArgs);
|
|
33
|
-
return new InferenceClient(clientArgs.inferenceServerUrl, httpClient, clientArgs.resize, (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId, clientArgs.modelComposition);
|
|
33
|
+
return new InferenceClient(clientArgs.inferenceServerUrl, httpClient, clientArgs.resize, (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId, clientArgs.modelComposition, clientArgs.inferenceServerApiVersion);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
static buildUiControllerClient(clientArgs) {
|
|
37
37
|
return new UiControllerClient(clientArgs.uiControllerUrl);
|
|
38
38
|
}
|
|
39
39
|
static build(clientArgs) {
|
|
40
|
+
var _a;
|
|
40
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
41
42
|
const uiControllerClient = UiControlClientDependencyBuilder.buildUiControllerClient(clientArgs);
|
|
42
43
|
const inferenceClient = yield UiControlClientDependencyBuilder.buildInferenceClient(clientArgs);
|
|
43
44
|
const stepReporter = new StepReporter(clientArgs.reporter);
|
|
45
|
+
const workspaceId = (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId;
|
|
44
46
|
return {
|
|
45
47
|
executionRuntime: new ExecutionRuntime(uiControllerClient, inferenceClient, stepReporter),
|
|
46
48
|
stepReporter,
|
|
49
|
+
workspaceId,
|
|
47
50
|
};
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
53
|
static getClientArgsWithDefaults(clientArgs) {
|
|
51
|
-
var _a, _b, _c, _d, _e;
|
|
54
|
+
var _a, _b, _c, _d, _e, _f;
|
|
52
55
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
56
|
return Object.assign(Object.assign({}, clientArgs), { context: {
|
|
54
57
|
isCi: (_b = (_a = clientArgs.context) === null || _a === void 0 ? void 0 : _a.isCi) !== null && _b !== void 0 ? _b : isCI,
|
|
55
|
-
}, credentials: readCredentials(clientArgs),
|
|
58
|
+
}, credentials: readCredentials(clientArgs), inferenceServerApiVersion: (_c = clientArgs.inferenceServerApiVersion) !== null && _c !== void 0 ? _c : 'v3', inferenceServerUrl: (_d = clientArgs.inferenceServerUrl) !== null && _d !== void 0 ? _d : 'https://inference.askui.com', proxyAgents: (_e = clientArgs.proxyAgents) !== null && _e !== void 0 ? _e : (yield envProxyAgents()), uiControllerUrl: (_f = clientArgs.uiControllerUrl) !== null && _f !== void 0 ? _f : 'http://127.0.0.1:6769' });
|
|
56
59
|
});
|
|
57
60
|
}
|
|
58
61
|
}
|
|
@@ -1,12 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY } from './dsl';
|
|
1
|
+
import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY, CommandExecutorContext } from './dsl';
|
|
3
2
|
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
|
|
4
3
|
import { Annotation } from '../core/annotation/annotation';
|
|
5
4
|
import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
|
|
6
5
|
import { DetectedElement } from '../core/model/annotation-result/detected-element';
|
|
7
6
|
import { ClientArgs } from './ui-controller-client-interface';
|
|
8
7
|
export declare type RelationsForConvenienceMethods = 'nearestTo' | 'leftOf' | 'above' | 'rightOf' | 'below' | 'contains';
|
|
8
|
+
export declare type TextMatchingOption = 'similar' | 'exact' | 'regex';
|
|
9
|
+
export declare type ElementExistsQueryType = 'otherElement' | 'switch' | 'element' | 'container' | 'checkbox' | 'element' | 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield';
|
|
10
|
+
export interface ElementExistsQueryText {
|
|
11
|
+
value: string;
|
|
12
|
+
matching?: TextMatchingOption;
|
|
13
|
+
}
|
|
14
|
+
export interface ElementExistsQueryRelation {
|
|
15
|
+
type: RelationsForConvenienceMethods;
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ElementExistsQuery {
|
|
19
|
+
type: keyof Pick<FluentFilters, ElementExistsQueryType>;
|
|
20
|
+
text?: ElementExistsQueryText;
|
|
21
|
+
relation?: ElementExistsQueryRelation;
|
|
22
|
+
}
|
|
23
|
+
export interface ExpectExistenceElement extends ElementExistsQuery {
|
|
24
|
+
exists: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ExpectAllExistResult {
|
|
27
|
+
allExist: boolean;
|
|
28
|
+
elements: ExpectExistenceElement[];
|
|
29
|
+
}
|
|
9
30
|
export declare class UiControlClient extends ApiCommands {
|
|
31
|
+
private workspaceId;
|
|
10
32
|
private executionRuntime;
|
|
11
33
|
private stepReporter;
|
|
12
34
|
private constructor();
|
|
@@ -34,8 +56,9 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
34
56
|
annotateInteractively(): Promise<void>;
|
|
35
57
|
private escapeSeparatorString;
|
|
36
58
|
private buildInstruction;
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
private getAIElementsByNames;
|
|
60
|
+
fluentCommandExecutor(instructionString: string, context?: CommandExecutorContext): Promise<void>;
|
|
61
|
+
getterExecutor(instruction: string, context?: CommandExecutorContext): Promise<DetectedElement[]>;
|
|
39
62
|
private secretText;
|
|
40
63
|
private getAndResetSecretText;
|
|
41
64
|
/**
|
|
@@ -190,8 +213,8 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
190
213
|
* @param {Object} params - Object containing required `label` property and
|
|
191
214
|
* optional `relation` property.
|
|
192
215
|
* @property {string} params.label - The label for the checkbox.
|
|
193
|
-
* @property {Object} params.relation - Object describing the relationship between
|
|
194
|
-
*
|
|
216
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
217
|
+
* the clicked checkbox and another element.
|
|
195
218
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
196
219
|
*/
|
|
197
220
|
clickCheckbox(params: {
|
|
@@ -213,7 +236,7 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
213
236
|
* @param {Object} params - Object containing required `label` property and
|
|
214
237
|
* optional `relation` property.
|
|
215
238
|
* @property {string} params.label - The label for the checkbox.
|
|
216
|
-
* @property {Object} params.relation - Object describing the relationship between
|
|
239
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
217
240
|
* the clicked checkbox and another element.
|
|
218
241
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
219
242
|
*/
|
|
@@ -266,41 +289,103 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
266
289
|
}): Promise<void>;
|
|
267
290
|
/**
|
|
268
291
|
* Click on a specific text.
|
|
269
|
-
* You can also use a RegEx or match the text exactly by
|
|
292
|
+
* You can also use a RegEx or match the text exactly by specifying the specific flag.
|
|
270
293
|
* Use a relation to find the text in relation to a specific text.
|
|
271
294
|
*
|
|
272
295
|
* **Examples:**
|
|
273
296
|
* ```typescript
|
|
274
297
|
* // Click text that matches exactly
|
|
275
|
-
* await aui.clickText({text: 'askui',
|
|
298
|
+
* await aui.clickText({text: 'askui', matching: 'similar'})
|
|
276
299
|
*
|
|
277
300
|
* // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
|
|
278
|
-
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*',
|
|
301
|
+
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', matching: 'regex'})
|
|
279
302
|
*
|
|
280
303
|
* // Click the text 'TERMINAL' that is left of the text 'Ports'
|
|
281
304
|
* await aui.clickText({
|
|
282
305
|
* text: 'TERMINAL',
|
|
283
|
-
*
|
|
306
|
+
* matching: "exact",
|
|
284
307
|
* relation: { type: 'leftOf', text: 'PORTS' }
|
|
285
308
|
* })
|
|
286
309
|
* ```
|
|
310
|
+
*
|
|
287
311
|
* @param {Object} params - Object containing required `text` property and optional properties
|
|
288
312
|
* for regular expression matching and relation.
|
|
289
313
|
* @property {string} params.text - The text to be clicked.
|
|
290
|
-
* @property {string} params.
|
|
291
|
-
*
|
|
292
|
-
* @property {Object} params.relation - Object describing the relationship between the
|
|
293
|
-
*
|
|
314
|
+
* @property {string} params.matching - Whether the text is matched using similarity,
|
|
315
|
+
* exact match or a regular expression.
|
|
316
|
+
* @property {Object} [params.relation] - Object describing the relationship between the
|
|
317
|
+
* clicked text and another element.
|
|
294
318
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
295
319
|
* @property {string} params.relation.text - The label or text associated with the
|
|
296
320
|
* related element or state.
|
|
297
321
|
*/
|
|
298
322
|
clickText(params: {
|
|
299
323
|
text: string;
|
|
300
|
-
|
|
324
|
+
matching: TextMatchingOption;
|
|
301
325
|
relation?: {
|
|
302
326
|
type: RelationsForConvenienceMethods;
|
|
303
327
|
text: string;
|
|
304
328
|
};
|
|
305
329
|
}): Promise<void>;
|
|
330
|
+
private evaluateMatchingProperty;
|
|
331
|
+
/**
|
|
332
|
+
* Check if one or multiple elements are detected.
|
|
333
|
+
*
|
|
334
|
+
* **Examples:**
|
|
335
|
+
* ```typescript
|
|
336
|
+
* await aui.expectAllExist([
|
|
337
|
+
* {
|
|
338
|
+
* type: 'text',
|
|
339
|
+
* text: {
|
|
340
|
+
* value: 'Switch to Dark',
|
|
341
|
+
* matching: 'similar'
|
|
342
|
+
* }
|
|
343
|
+
* },
|
|
344
|
+
* ]);
|
|
345
|
+
*
|
|
346
|
+
* // Check for existence of multiple elements
|
|
347
|
+
* await aui.expectAllExist([
|
|
348
|
+
* {
|
|
349
|
+
* type: 'textfield',
|
|
350
|
+
* relation: {
|
|
351
|
+
* type: 'rightOf',
|
|
352
|
+
* text: 'Email:'
|
|
353
|
+
* }
|
|
354
|
+
* },
|
|
355
|
+
* {
|
|
356
|
+
* type: 'element',
|
|
357
|
+
* text: {
|
|
358
|
+
* value: 'Switch to Dark'
|
|
359
|
+
* }
|
|
360
|
+
* },
|
|
361
|
+
* ]);
|
|
362
|
+
*
|
|
363
|
+
* // Validate existence
|
|
364
|
+
* const exists = await aui.expectAllExist([...]);
|
|
365
|
+
* exists.allExist // true when every element exists
|
|
366
|
+
*
|
|
367
|
+
* // Check which elements do not exist
|
|
368
|
+
* // with the elements property
|
|
369
|
+
* const nonExistentElements = exists.elements.filter((e) => e.exists===false)
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @param {ElementExistsQuery[]} query - Objects containing the required property
|
|
373
|
+
* 'type' and the optional properties
|
|
374
|
+
* 'text' and 'relation'.
|
|
375
|
+
* @property {string} query.type - The type of the element: 'otherElement' | 'switch' |
|
|
376
|
+
* 'element' | 'container' | 'checkbox' | 'element' |
|
|
377
|
+
* 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield'
|
|
378
|
+
* @property {Object} [query.text] - Object containing value and matching strategy.
|
|
379
|
+
* @property {string} query.text.value - The text to match for.
|
|
380
|
+
* @property {string} [query.text.matching] - Whether the text is matched using similarity,
|
|
381
|
+
* exact match or a regular expression.
|
|
382
|
+
* @property {Object} [query.relation] - Object describing the relationship between the
|
|
383
|
+
* clicked text and another element.
|
|
384
|
+
* @property {RelationsForConvenienceMethods} query.relation.type - The type of relation.
|
|
385
|
+
* @property {string} query.relation.text - The label or text associated with the
|
|
386
|
+
* related element or state.
|
|
387
|
+
* @returns {ExpectAllExistResult.allExist} - If every element exists.
|
|
388
|
+
* @returns {ExpectAllExistResult.elements} - ExpectExistenceElement[].
|
|
389
|
+
*/
|
|
390
|
+
expectAllExist(query: ElementExistsQuery[]): Promise<ExpectAllExistResult>;
|
|
306
391
|
}
|
|
@@ -7,15 +7,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import ValidationError from 'yup
|
|
10
|
+
import { ValidationError } from 'yup';
|
|
11
11
|
import { CustomElement } from '../core/model/custom-element';
|
|
12
12
|
import { ApiCommands, Separators, } from './dsl';
|
|
13
13
|
import { AnnotationWriter } from '../core/annotation/annotation-writer';
|
|
14
14
|
import { logger } from '../lib/logger';
|
|
15
15
|
import { UiControlClientDependencyBuilder } from './ui-control-client-dependency-builder';
|
|
16
|
+
import { AIElementCollection } from '../core/ai-element/ai-element-collection';
|
|
16
17
|
export class UiControlClient extends ApiCommands {
|
|
17
|
-
constructor(executionRuntime, stepReporter) {
|
|
18
|
+
constructor(workspaceId, executionRuntime, stepReporter) {
|
|
18
19
|
super();
|
|
20
|
+
this.workspaceId = workspaceId;
|
|
19
21
|
this.executionRuntime = executionRuntime;
|
|
20
22
|
this.stepReporter = stepReporter;
|
|
21
23
|
this.secretText = undefined;
|
|
@@ -24,8 +26,8 @@ export class UiControlClient extends ApiCommands {
|
|
|
24
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
27
|
const builder = UiControlClientDependencyBuilder;
|
|
26
28
|
const clientArgsWithDefaults = yield builder.getClientArgsWithDefaults(clientArgs);
|
|
27
|
-
const { executionRuntime, stepReporter } = yield builder.build(clientArgsWithDefaults);
|
|
28
|
-
return new UiControlClient(executionRuntime, stepReporter);
|
|
29
|
+
const { workspaceId, executionRuntime, stepReporter, } = yield builder.build(clientArgsWithDefaults);
|
|
30
|
+
return new UiControlClient(workspaceId, executionRuntime, stepReporter);
|
|
29
31
|
});
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
@@ -119,9 +121,20 @@ export class UiControlClient extends ApiCommands {
|
|
|
119
121
|
};
|
|
120
122
|
});
|
|
121
123
|
}
|
|
122
|
-
|
|
124
|
+
getAIElementsByNames(names) {
|
|
123
125
|
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
-
|
|
126
|
+
// eslint-disable-next-line max-len
|
|
127
|
+
const workspaceAIElementCollection = yield AIElementCollection.collectForWorkspaceId(this.workspaceId);
|
|
128
|
+
return workspaceAIElementCollection.getByNames(names);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
fluentCommandExecutor(instructionString, context = { customElementsJson: [], aiElementNames: [] }) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
const aiElements = yield this.getAIElementsByNames(context.aiElementNames);
|
|
134
|
+
const instruction = yield this.buildInstruction(instructionString, [
|
|
135
|
+
...context.customElementsJson,
|
|
136
|
+
...aiElements,
|
|
137
|
+
]);
|
|
125
138
|
logger.debug(instruction);
|
|
126
139
|
try {
|
|
127
140
|
yield this.stepReporter.resetStep(instruction);
|
|
@@ -135,12 +148,16 @@ export class UiControlClient extends ApiCommands {
|
|
|
135
148
|
}
|
|
136
149
|
});
|
|
137
150
|
}
|
|
138
|
-
getterExecutor(instruction,
|
|
151
|
+
getterExecutor(instruction, context = { customElementsJson: [], aiElementNames: [] }) {
|
|
139
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
-
const
|
|
153
|
+
const aiElements = yield this.getAIElementsByNames(context.aiElementNames);
|
|
154
|
+
const customElements = yield CustomElement.fromJsonListWithImagePathOrImage(context.customElementsJson);
|
|
141
155
|
const stringWithoutSeparators = this.escapeSeparatorString(instruction);
|
|
142
156
|
logger.debug(stringWithoutSeparators);
|
|
143
|
-
return this.executionRuntime.getDetectedElements(instruction,
|
|
157
|
+
return this.executionRuntime.getDetectedElements(instruction, [
|
|
158
|
+
...customElements,
|
|
159
|
+
...aiElements,
|
|
160
|
+
]);
|
|
144
161
|
});
|
|
145
162
|
}
|
|
146
163
|
getAndResetSecretText() {
|
|
@@ -325,30 +342,22 @@ export class UiControlClient extends ApiCommands {
|
|
|
325
342
|
}
|
|
326
343
|
// eslint-disable-next-line class-methods-use-this
|
|
327
344
|
evaluateRelation(command, relation, text) {
|
|
328
|
-
let commando = command;
|
|
329
345
|
switch (relation) {
|
|
330
|
-
case 'nearestTo':
|
|
331
|
-
commando = command.nearestTo().text(text);
|
|
332
|
-
break;
|
|
333
346
|
case 'leftOf':
|
|
334
|
-
|
|
335
|
-
break;
|
|
347
|
+
return command.leftOf().text(text);
|
|
336
348
|
case 'above':
|
|
337
|
-
|
|
338
|
-
break;
|
|
349
|
+
return command.above().text(text);
|
|
339
350
|
case 'rightOf':
|
|
340
|
-
|
|
341
|
-
break;
|
|
351
|
+
return command.rightOf().text(text);
|
|
342
352
|
case 'below':
|
|
343
|
-
|
|
344
|
-
break;
|
|
353
|
+
return command.below().text(text);
|
|
345
354
|
case 'contains':
|
|
346
|
-
|
|
347
|
-
|
|
355
|
+
return command.contains().text(text);
|
|
356
|
+
case 'nearestTo':
|
|
357
|
+
return command.nearestTo().text(text);
|
|
348
358
|
default:
|
|
349
|
-
throw new ValidationError('
|
|
359
|
+
throw new ValidationError(`'relation' has to be 'nearestTo', 'leftOf', 'above', 'rightOf', 'below' or 'contains' but was '${relation}'`);
|
|
350
360
|
}
|
|
351
|
-
return commando;
|
|
352
361
|
}
|
|
353
362
|
/**
|
|
354
363
|
* Click a button with a specific label.
|
|
@@ -394,8 +403,8 @@ export class UiControlClient extends ApiCommands {
|
|
|
394
403
|
* @param {Object} params - Object containing required `label` property and
|
|
395
404
|
* optional `relation` property.
|
|
396
405
|
* @property {string} params.label - The label for the checkbox.
|
|
397
|
-
* @property {Object} params.relation - Object describing the relationship between
|
|
398
|
-
*
|
|
406
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
407
|
+
* the clicked checkbox and another element.
|
|
399
408
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
400
409
|
*/
|
|
401
410
|
clickCheckbox(params) {
|
|
@@ -423,7 +432,7 @@ export class UiControlClient extends ApiCommands {
|
|
|
423
432
|
* @param {Object} params - Object containing required `label` property and
|
|
424
433
|
* optional `relation` property.
|
|
425
434
|
* @property {string} params.label - The label for the checkbox.
|
|
426
|
-
* @property {Object} params.relation - Object describing the relationship between
|
|
435
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
427
436
|
* the clicked checkbox and another element.
|
|
428
437
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
429
438
|
*/
|
|
@@ -487,31 +496,32 @@ export class UiControlClient extends ApiCommands {
|
|
|
487
496
|
}
|
|
488
497
|
/**
|
|
489
498
|
* Click on a specific text.
|
|
490
|
-
* You can also use a RegEx or match the text exactly by
|
|
499
|
+
* You can also use a RegEx or match the text exactly by specifying the specific flag.
|
|
491
500
|
* Use a relation to find the text in relation to a specific text.
|
|
492
501
|
*
|
|
493
502
|
* **Examples:**
|
|
494
503
|
* ```typescript
|
|
495
504
|
* // Click text that matches exactly
|
|
496
|
-
* await aui.clickText({text: 'askui',
|
|
505
|
+
* await aui.clickText({text: 'askui', matching: 'similar'})
|
|
497
506
|
*
|
|
498
507
|
* // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
|
|
499
|
-
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*',
|
|
508
|
+
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', matching: 'regex'})
|
|
500
509
|
*
|
|
501
510
|
* // Click the text 'TERMINAL' that is left of the text 'Ports'
|
|
502
511
|
* await aui.clickText({
|
|
503
512
|
* text: 'TERMINAL',
|
|
504
|
-
*
|
|
513
|
+
* matching: "exact",
|
|
505
514
|
* relation: { type: 'leftOf', text: 'PORTS' }
|
|
506
515
|
* })
|
|
507
516
|
* ```
|
|
517
|
+
*
|
|
508
518
|
* @param {Object} params - Object containing required `text` property and optional properties
|
|
509
519
|
* for regular expression matching and relation.
|
|
510
520
|
* @property {string} params.text - The text to be clicked.
|
|
511
|
-
* @property {string} params.
|
|
512
|
-
*
|
|
513
|
-
* @property {Object} params.relation - Object describing the relationship between the
|
|
514
|
-
*
|
|
521
|
+
* @property {string} params.matching - Whether the text is matched using similarity,
|
|
522
|
+
* exact match or a regular expression.
|
|
523
|
+
* @property {Object} [params.relation] - Object describing the relationship between the
|
|
524
|
+
* clicked text and another element.
|
|
515
525
|
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
516
526
|
* @property {string} params.relation.text - The label or text associated with the
|
|
517
527
|
* related element or state.
|
|
@@ -519,23 +529,106 @@ export class UiControlClient extends ApiCommands {
|
|
|
519
529
|
clickText(params) {
|
|
520
530
|
return __awaiter(this, void 0, void 0, function* () {
|
|
521
531
|
let command = this.click().text();
|
|
522
|
-
|
|
523
|
-
case 'similar':
|
|
524
|
-
command = command.withText(params.text);
|
|
525
|
-
break;
|
|
526
|
-
case 'exact':
|
|
527
|
-
command = command.withExactText(params.text);
|
|
528
|
-
break;
|
|
529
|
-
case 'regex':
|
|
530
|
-
command = command.withTextRegex(params.text);
|
|
531
|
-
break;
|
|
532
|
-
default:
|
|
533
|
-
throw new ValidationError('"type" must be "similar", "exact" or "regex"');
|
|
534
|
-
}
|
|
532
|
+
command = this.evaluateMatchingProperty(command, { value: params.text, matching: params.matching });
|
|
535
533
|
if (params.relation) {
|
|
536
534
|
command = this.evaluateRelation(command, params.relation.type, params.relation.text);
|
|
537
535
|
}
|
|
538
536
|
yield command.exec();
|
|
539
537
|
});
|
|
540
538
|
}
|
|
539
|
+
// eslint-disable-next-line class-methods-use-this
|
|
540
|
+
evaluateMatchingProperty(command, text) {
|
|
541
|
+
var _a;
|
|
542
|
+
switch ((_a = text.matching) !== null && _a !== void 0 ? _a : 'similar') {
|
|
543
|
+
case 'exact':
|
|
544
|
+
return command.withExactText(text.value);
|
|
545
|
+
case 'regex':
|
|
546
|
+
return command.withTextRegex(text.value);
|
|
547
|
+
case 'similar':
|
|
548
|
+
return command.withText(text.value);
|
|
549
|
+
default:
|
|
550
|
+
throw new ValidationError(`'text.matching' property has to be 'similar', 'exact' or 'regex' but was '${text.matching}'`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Check if one or multiple elements are detected.
|
|
555
|
+
*
|
|
556
|
+
* **Examples:**
|
|
557
|
+
* ```typescript
|
|
558
|
+
* await aui.expectAllExist([
|
|
559
|
+
* {
|
|
560
|
+
* type: 'text',
|
|
561
|
+
* text: {
|
|
562
|
+
* value: 'Switch to Dark',
|
|
563
|
+
* matching: 'similar'
|
|
564
|
+
* }
|
|
565
|
+
* },
|
|
566
|
+
* ]);
|
|
567
|
+
*
|
|
568
|
+
* // Check for existence of multiple elements
|
|
569
|
+
* await aui.expectAllExist([
|
|
570
|
+
* {
|
|
571
|
+
* type: 'textfield',
|
|
572
|
+
* relation: {
|
|
573
|
+
* type: 'rightOf',
|
|
574
|
+
* text: 'Email:'
|
|
575
|
+
* }
|
|
576
|
+
* },
|
|
577
|
+
* {
|
|
578
|
+
* type: 'element',
|
|
579
|
+
* text: {
|
|
580
|
+
* value: 'Switch to Dark'
|
|
581
|
+
* }
|
|
582
|
+
* },
|
|
583
|
+
* ]);
|
|
584
|
+
*
|
|
585
|
+
* // Validate existence
|
|
586
|
+
* const exists = await aui.expectAllExist([...]);
|
|
587
|
+
* exists.allExist // true when every element exists
|
|
588
|
+
*
|
|
589
|
+
* // Check which elements do not exist
|
|
590
|
+
* // with the elements property
|
|
591
|
+
* const nonExistentElements = exists.elements.filter((e) => e.exists===false)
|
|
592
|
+
* ```
|
|
593
|
+
*
|
|
594
|
+
* @param {ElementExistsQuery[]} query - Objects containing the required property
|
|
595
|
+
* 'type' and the optional properties
|
|
596
|
+
* 'text' and 'relation'.
|
|
597
|
+
* @property {string} query.type - The type of the element: 'otherElement' | 'switch' |
|
|
598
|
+
* 'element' | 'container' | 'checkbox' | 'element' |
|
|
599
|
+
* 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield'
|
|
600
|
+
* @property {Object} [query.text] - Object containing value and matching strategy.
|
|
601
|
+
* @property {string} query.text.value - The text to match for.
|
|
602
|
+
* @property {string} [query.text.matching] - Whether the text is matched using similarity,
|
|
603
|
+
* exact match or a regular expression.
|
|
604
|
+
* @property {Object} [query.relation] - Object describing the relationship between the
|
|
605
|
+
* clicked text and another element.
|
|
606
|
+
* @property {RelationsForConvenienceMethods} query.relation.type - The type of relation.
|
|
607
|
+
* @property {string} query.relation.text - The label or text associated with the
|
|
608
|
+
* related element or state.
|
|
609
|
+
* @returns {ExpectAllExistResult.allExist} - If every element exists.
|
|
610
|
+
* @returns {ExpectAllExistResult.elements} - ExpectExistenceElement[].
|
|
611
|
+
*/
|
|
612
|
+
expectAllExist(query) {
|
|
613
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
614
|
+
const elements = yield query.reduce((accumulatorPromise, subquery) => __awaiter(this, void 0, void 0, function* () {
|
|
615
|
+
const acc = yield accumulatorPromise;
|
|
616
|
+
const command = this.get()[subquery.type]();
|
|
617
|
+
let finalCommand = subquery.text !== undefined
|
|
618
|
+
? this.evaluateMatchingProperty(command, subquery.text)
|
|
619
|
+
: command;
|
|
620
|
+
if (subquery.relation) {
|
|
621
|
+
finalCommand = this.evaluateRelation(finalCommand, subquery.relation.type, subquery.relation.text);
|
|
622
|
+
}
|
|
623
|
+
return [
|
|
624
|
+
...acc,
|
|
625
|
+
Object.assign(Object.assign({}, subquery), { exists: (yield finalCommand.exec()).length > 0 }),
|
|
626
|
+
];
|
|
627
|
+
}), Promise.resolve([]));
|
|
628
|
+
return {
|
|
629
|
+
elements,
|
|
630
|
+
allExist: elements.every((el) => el.exists),
|
|
631
|
+
};
|
|
632
|
+
});
|
|
633
|
+
}
|
|
541
634
|
}
|
|
@@ -53,9 +53,11 @@ export interface ClientArgs {
|
|
|
53
53
|
readonly modelComposition?: ModelCompositionBranch[];
|
|
54
54
|
readonly reporter?: Reporter | Reporter[] | undefined;
|
|
55
55
|
readonly context?: ContextArgs | undefined;
|
|
56
|
+
readonly inferenceServerApiVersion?: string;
|
|
56
57
|
}
|
|
57
58
|
export interface ClientArgsWithDefaults extends ClientArgs {
|
|
58
59
|
readonly uiControllerUrl: string;
|
|
59
60
|
readonly inferenceServerUrl: string;
|
|
60
61
|
readonly context: Context;
|
|
62
|
+
readonly inferenceServerApiVersion: string;
|
|
61
63
|
}
|
|
@@ -18,6 +18,7 @@ export declare class UiControllerClient {
|
|
|
18
18
|
private onMessage;
|
|
19
19
|
connect(): Promise<UiControllerClientConnectionState>;
|
|
20
20
|
disconnect(): void;
|
|
21
|
+
private checkConnection;
|
|
21
22
|
private sendAndReceive;
|
|
22
23
|
private send;
|
|
23
24
|
requestScreenshot(): Promise<CaptureScreenshotResponse>;
|
|
@@ -4,6 +4,7 @@ import { logger } from '../lib/logger';
|
|
|
4
4
|
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
|
|
5
5
|
import { ReadRecordingResponseStreamHandler } from './read-recording-response-stream-handler';
|
|
6
6
|
import { UiControllerClientError } from './ui-controller-client-error';
|
|
7
|
+
import { UiControllerNotConnectedError } from './ui-controller-not-connected-error';
|
|
7
8
|
export class UiControllerClient {
|
|
8
9
|
constructor(url) {
|
|
9
10
|
this.url = url;
|
|
@@ -34,7 +35,9 @@ export class UiControllerClient {
|
|
|
34
35
|
return new Promise((resolve, reject) => {
|
|
35
36
|
try {
|
|
36
37
|
this.ws = new WebSocket(this.url);
|
|
37
|
-
this.ws.on('message', (data) => {
|
|
38
|
+
this.ws.on('message', (data) => {
|
|
39
|
+
this.onMessage(data);
|
|
40
|
+
});
|
|
38
41
|
this.ws.on('open', () => {
|
|
39
42
|
this.connectionState = UiControllerClientConnectionState.CONNECTED;
|
|
40
43
|
resolve(this.connectionState);
|
|
@@ -55,7 +58,13 @@ export class UiControllerClient {
|
|
|
55
58
|
var _a;
|
|
56
59
|
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
|
|
57
60
|
}
|
|
61
|
+
checkConnection() {
|
|
62
|
+
if (this.connectionState !== UiControllerClientConnectionState.CONNECTED) {
|
|
63
|
+
throw new UiControllerNotConnectedError();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
58
66
|
sendAndReceive(msg, requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
|
|
67
|
+
this.checkConnection();
|
|
59
68
|
return new Promise((resolve, reject) => {
|
|
60
69
|
this.currentResolve = resolve;
|
|
61
70
|
this.currentReject = reject;
|
|
@@ -69,6 +78,7 @@ export class UiControllerClient {
|
|
|
69
78
|
});
|
|
70
79
|
}
|
|
71
80
|
send(msg, _requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
|
|
81
|
+
this.checkConnection();
|
|
72
82
|
if (!this.currentReject || !this.currentResolve) {
|
|
73
83
|
throw new UiControllerClientError('Request is not finished! It is not possible to have multiple requests at the same time.');
|
|
74
84
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { UiControllerClientError } from './ui-controller-client-error';
|
|
2
|
+
export class UiControllerNotConnectedError extends UiControllerClientError {
|
|
3
|
+
constructor() {
|
|
4
|
+
super('UI Controller is not connected. Did you call `UiControlClient.connect()`'
|
|
5
|
+
+ ' before trying to interact with the UI Controller / OS?');
|
|
6
|
+
this.name = 'UiControllerNotConnectedError';
|
|
7
|
+
}
|
|
8
|
+
}
|
package/dist/esm/main.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { UiController } from './lib';
|
|
2
|
-
export
|
|
2
|
+
export * from './execution';
|
|
3
3
|
export { Instruction, Reporter, ReporterConfig, Snapshot, SnapshotDetailLevel, Step, StepStatus, StepStatusEnd, } from './core/reporting';
|
|
4
4
|
export { Annotation } from './core/annotation/annotation';
|
|
5
5
|
export { DetectedElement } from './core/model/annotation-result/detected-element';
|
package/dist/esm/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { UiController } from './lib';
|
|
2
|
-
export
|
|
2
|
+
export * from './execution';
|
|
3
3
|
export { Annotation } from './core/annotation/annotation';
|
|
4
4
|
export { DetectedElement } from './core/model/annotation-result/detected-element';
|
|
5
5
|
export { LogLevels } from './shared';
|