askui 0.30.0 → 0.31.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/cache/cache-config.d.ts +5 -0
- package/dist/cjs/core/cache/cache-config.js +2 -0
- package/dist/cjs/core/cache/cache-entry-reference.d.ts +7 -0
- package/dist/cjs/core/cache/cache-entry-reference.js +20 -0
- package/dist/cjs/core/cache/cache-entry.d.ts +11 -0
- package/dist/cjs/core/cache/cache-entry.js +47 -0
- package/dist/cjs/core/cache/cache-interface.d.ts +11 -0
- package/dist/cjs/core/cache/cache-interface.js +2 -0
- package/dist/cjs/core/cache/cache-manager.d.ts +24 -0
- package/dist/cjs/core/cache/cache-manager.js +145 -0
- package/dist/cjs/core/cache/cahe-file.d.ts +19 -0
- package/dist/cjs/core/cache/cahe-file.js +128 -0
- package/dist/cjs/core/cache/dummy-cache-manager.d.ts +12 -0
- package/dist/cjs/core/cache/dummy-cache-manager.js +27 -0
- package/dist/cjs/core/cache/image-reference.d.ts +10 -0
- package/dist/cjs/core/cache/image-reference.js +40 -0
- package/dist/cjs/core/cache/index.d.ts +7 -0
- package/dist/cjs/core/cache/index.js +13 -0
- package/dist/cjs/core/model/annotation-result/boundary-box.js +1 -1
- package/dist/cjs/core/model/custom-element.d.ts +1 -0
- package/dist/cjs/core/model/custom-element.js +3 -0
- package/dist/cjs/core/ui-control-commands/action.d.ts +1 -0
- package/dist/cjs/core/ui-control-commands/action.js +10 -2
- package/dist/cjs/core/ui-control-commands/control-command.d.ts +1 -0
- package/dist/cjs/core/ui-control-commands/control-command.js +7 -0
- package/dist/cjs/execution/dsl.d.ts +12 -5
- package/dist/cjs/execution/dsl.js +30 -15
- package/dist/cjs/execution/execution-runtime.d.ts +1 -1
- package/dist/cjs/execution/execution-runtime.js +21 -17
- package/dist/cjs/execution/inference-client.d.ts +5 -3
- package/dist/cjs/execution/inference-client.js +22 -3
- package/dist/cjs/execution/ui-control-client-dependency-builder.js +6 -1
- package/dist/cjs/execution/ui-control-client.d.ts +2 -1
- package/dist/cjs/execution/ui-control-client.js +28 -11
- package/dist/cjs/execution/ui-controller-client-interface.d.ts +2 -0
- package/dist/cjs/utils/base_64_image/base-64-image.d.ts +2 -0
- package/dist/cjs/utils/base_64_image/base-64-image.js +27 -4
- package/dist/esm/core/cache/cache-config.d.ts +5 -0
- package/dist/esm/core/cache/cache-config.js +1 -0
- package/dist/esm/core/cache/cache-entry-reference.d.ts +7 -0
- package/dist/esm/core/cache/cache-entry-reference.js +16 -0
- package/dist/esm/core/cache/cache-entry.d.ts +11 -0
- package/dist/esm/core/cache/cache-entry.js +43 -0
- package/dist/esm/core/cache/cache-interface.d.ts +11 -0
- package/dist/esm/core/cache/cache-interface.js +1 -0
- package/dist/esm/core/cache/cache-manager.d.ts +24 -0
- package/dist/esm/core/cache/cache-manager.js +141 -0
- package/dist/esm/core/cache/cahe-file.d.ts +19 -0
- package/dist/esm/core/cache/cahe-file.js +121 -0
- package/dist/esm/core/cache/dummy-cache-manager.d.ts +12 -0
- package/dist/esm/core/cache/dummy-cache-manager.js +23 -0
- package/dist/esm/core/cache/image-reference.d.ts +10 -0
- package/dist/esm/core/cache/image-reference.js +36 -0
- package/dist/esm/core/cache/index.d.ts +7 -0
- package/dist/esm/core/cache/index.js +5 -0
- package/dist/esm/core/model/annotation-result/boundary-box.js +1 -1
- package/dist/esm/core/model/custom-element.d.ts +1 -0
- package/dist/esm/core/model/custom-element.js +3 -0
- package/dist/esm/core/ui-control-commands/action.d.ts +1 -0
- package/dist/esm/core/ui-control-commands/action.js +10 -2
- package/dist/esm/core/ui-control-commands/control-command.d.ts +1 -0
- package/dist/esm/core/ui-control-commands/control-command.js +7 -0
- package/dist/esm/execution/dsl.d.ts +12 -5
- package/dist/esm/execution/dsl.js +30 -15
- package/dist/esm/execution/execution-runtime.d.ts +1 -1
- package/dist/esm/execution/execution-runtime.js +21 -17
- package/dist/esm/execution/inference-client.d.ts +5 -3
- package/dist/esm/execution/inference-client.js +22 -3
- package/dist/esm/execution/ui-control-client-dependency-builder.js +6 -1
- package/dist/esm/execution/ui-control-client.d.ts +2 -1
- package/dist/esm/execution/ui-control-client.js +28 -11
- package/dist/esm/execution/ui-controller-client-interface.d.ts +2 -0
- package/dist/esm/utils/base_64_image/base-64-image.d.ts +2 -0
- package/dist/esm/utils/base_64_image/base-64-image.js +27 -4
- package/package.json +1 -1
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
/* eslint-disable max-classes-per-file */
|
|
4
4
|
/* eslint-disable max-len */
|
|
5
5
|
// Autogenerated from typescript.template file
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
6
15
|
function isStackTraceCodeline(line) {
|
|
7
16
|
return /[ \t]+at .+/.test(line);
|
|
8
17
|
}
|
|
@@ -14,21 +23,18 @@ function splitStackTrace(stacktrace) {
|
|
|
14
23
|
return { head: errorStacktraceHead, codelines: errorStacktraceCodeLines };
|
|
15
24
|
}
|
|
16
25
|
function rewriteStackTraceForError(error, newStackTrace) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
errorCopy.stack = newStackTrace;
|
|
20
|
-
return errorCopy;
|
|
21
|
-
}
|
|
22
|
-
const errorStacktraceSplit = splitStackTrace(error.stack);
|
|
26
|
+
var _a;
|
|
27
|
+
const errorStacktraceSplit = splitStackTrace((_a = error.stack) !== null && _a !== void 0 ? _a : '');
|
|
23
28
|
const newStacktraceSplit = splitStackTrace(newStackTrace);
|
|
24
|
-
|
|
29
|
+
// eslint-disable-next-line no-param-reassign
|
|
30
|
+
error.stack = [
|
|
25
31
|
...errorStacktraceSplit.head,
|
|
26
32
|
...newStacktraceSplit.codelines,
|
|
27
33
|
' ',
|
|
28
34
|
...errorStacktraceSplit.head,
|
|
29
35
|
...errorStacktraceSplit.codelines,
|
|
30
36
|
].join('\n');
|
|
31
|
-
return
|
|
37
|
+
return error;
|
|
32
38
|
}
|
|
33
39
|
export var Separators;
|
|
34
40
|
(function (Separators) {
|
|
@@ -52,7 +58,7 @@ class FluentBase {
|
|
|
52
58
|
});
|
|
53
59
|
return paramsList;
|
|
54
60
|
}
|
|
55
|
-
fluentCommandStringBuilder(modelComposition, currentInstruction = '', paramsList = new Map()) {
|
|
61
|
+
fluentCommandStringBuilder(modelComposition = [], skipCache = false, retryStrategy, currentInstruction = '', paramsList = new Map()) {
|
|
56
62
|
const newCurrentInstruction = `${this.textStr} ${currentInstruction}`;
|
|
57
63
|
const newParamsList = FluentBase.addParams(paramsList, this._params);
|
|
58
64
|
if (this instanceof FluentCommand) {
|
|
@@ -62,12 +68,12 @@ class FluentBase {
|
|
|
62
68
|
return fluentCommand.fluentCommandExecutor(newCurrentInstruction.trim(), modelComposition, {
|
|
63
69
|
customElementsJson: customElements,
|
|
64
70
|
aiElementNames,
|
|
65
|
-
});
|
|
71
|
+
}, skipCache, retryStrategy);
|
|
66
72
|
}
|
|
67
73
|
if (!this.prev) {
|
|
68
74
|
throw new Error('Prev element not defined');
|
|
69
75
|
}
|
|
70
|
-
return this.prev.fluentCommandStringBuilder(modelComposition, newCurrentInstruction, newParamsList);
|
|
76
|
+
return this.prev.fluentCommandStringBuilder(modelComposition, skipCache, retryStrategy, newCurrentInstruction, newParamsList);
|
|
71
77
|
}
|
|
72
78
|
getterStringBuilder(currentInstruction = '', paramsList = new Map()) {
|
|
73
79
|
const newCurrentInstruction = `${this.textStr} ${currentInstruction}`;
|
|
@@ -90,10 +96,10 @@ class FluentBase {
|
|
|
90
96
|
get params() { return this._params; }
|
|
91
97
|
}
|
|
92
98
|
export class Exec extends FluentBase {
|
|
93
|
-
exec(
|
|
99
|
+
exec(execOptions) {
|
|
94
100
|
const originStacktrace = { stack: '' };
|
|
95
101
|
Error.captureStackTrace(originStacktrace, this.exec);
|
|
96
|
-
return this.fluentCommandStringBuilder(modelComposition).catch((err) => Promise.reject(rewriteStackTraceForError(err, originStacktrace.stack)));
|
|
102
|
+
return this.fluentCommandStringBuilder(execOptions === null || execOptions === void 0 ? void 0 : execOptions.modelComposition, execOptions === null || execOptions === void 0 ? void 0 : execOptions.skipCache, execOptions === null || execOptions === void 0 ? void 0 : execOptions.retryStrategy).catch((err) => Promise.reject(rewriteStackTraceForError(err, originStacktrace.stack)));
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
// Filters
|
|
@@ -1043,10 +1049,10 @@ export class FluentFiltersOrRelations extends FluentFilters {
|
|
|
1043
1049
|
this._textStr += 'contains';
|
|
1044
1050
|
return new FluentFilters(this);
|
|
1045
1051
|
}
|
|
1046
|
-
exec(
|
|
1052
|
+
exec(execOptions) {
|
|
1047
1053
|
const originStacktrace = { stack: '' };
|
|
1048
1054
|
Error.captureStackTrace(originStacktrace, this.exec);
|
|
1049
|
-
return this.fluentCommandStringBuilder(modelComposition).catch((err) => Promise.reject(rewriteStackTraceForError(err, originStacktrace.stack)));
|
|
1055
|
+
return this.fluentCommandStringBuilder(execOptions === null || execOptions === void 0 ? void 0 : execOptions.modelComposition, execOptions === null || execOptions === void 0 ? void 0 : execOptions.skipCache, execOptions === null || execOptions === void 0 ? void 0 : execOptions.retryStrategy).catch((err) => Promise.reject(rewriteStackTraceForError(err, originStacktrace.stack)));
|
|
1050
1056
|
}
|
|
1051
1057
|
}
|
|
1052
1058
|
// Filters
|
|
@@ -2055,6 +2061,15 @@ export class FluentFiltersOrRelationsCondition extends FluentFiltersCondition {
|
|
|
2055
2061
|
}
|
|
2056
2062
|
}
|
|
2057
2063
|
class ExecCondition extends Exec {
|
|
2064
|
+
exec(execOptions) {
|
|
2065
|
+
const _super = Object.create(null, {
|
|
2066
|
+
exec: { get: () => super.exec }
|
|
2067
|
+
});
|
|
2068
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2069
|
+
const options = Object.assign(Object.assign({}, execOptions), { skipCache: true });
|
|
2070
|
+
return _super.exec.call(this, options);
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2058
2073
|
}
|
|
2059
2074
|
// Commands
|
|
2060
2075
|
export class FluentCommand extends FluentBase {
|
|
@@ -21,7 +21,7 @@ export declare class ExecutionRuntime {
|
|
|
21
21
|
stopVideoRecording(): Promise<void>;
|
|
22
22
|
readVideoRecording(): Promise<string>;
|
|
23
23
|
requestControl(controlCommand: ControlCommand): Promise<void>;
|
|
24
|
-
executeInstruction(instruction: Instruction, modelComposition: ModelCompositionBranch[]): Promise<void>;
|
|
24
|
+
executeInstruction(instruction: Instruction, modelComposition: ModelCompositionBranch[], skipCache?: boolean, retryStrategy?: RetryStrategy): Promise<void>;
|
|
25
25
|
private readonly EXEC_REPETITION_COUNT;
|
|
26
26
|
private executeCommandRepeatedly;
|
|
27
27
|
/**
|
|
@@ -25,10 +25,12 @@ export class ExecutionRuntime {
|
|
|
25
25
|
}
|
|
26
26
|
connect() {
|
|
27
27
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
this.inferenceClient.cacheManager.loadFromFile();
|
|
28
29
|
return this.uiControllerClient.connect();
|
|
29
30
|
});
|
|
30
31
|
}
|
|
31
32
|
disconnect() {
|
|
33
|
+
this.inferenceClient.cacheManager.saveToFile();
|
|
32
34
|
this.uiControllerClient.disconnect();
|
|
33
35
|
}
|
|
34
36
|
startVideoRecording() {
|
|
@@ -52,10 +54,10 @@ export class ExecutionRuntime {
|
|
|
52
54
|
yield this.uiControllerClient.requestControl(controlCommand);
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
|
-
executeInstruction(
|
|
56
|
-
return __awaiter(this,
|
|
57
|
+
executeInstruction(instruction_1, modelComposition_1) {
|
|
58
|
+
return __awaiter(this, arguments, void 0, function* (instruction, modelComposition, skipCache = false, retryStrategy) {
|
|
57
59
|
var _a, _b, _c;
|
|
58
|
-
const controlCommand = yield this.predictCommandWithRetry(instruction, modelComposition);
|
|
60
|
+
const controlCommand = yield this.predictCommandWithRetry(instruction, modelComposition, skipCache, retryStrategy);
|
|
59
61
|
if (controlCommand.code === ControlCommandCode.OK) {
|
|
60
62
|
return this.requestControl(controlCommand);
|
|
61
63
|
}
|
|
@@ -95,19 +97,20 @@ export class ExecutionRuntime {
|
|
|
95
97
|
* --> retry with linear back-off
|
|
96
98
|
*/
|
|
97
99
|
/* eslint-disable-next-line consistent-return */
|
|
98
|
-
predictCommandWithRetry(
|
|
99
|
-
return __awaiter(this,
|
|
100
|
+
predictCommandWithRetry(instruction_1, modelComposition_1) {
|
|
101
|
+
return __awaiter(this, arguments, void 0, function* (instruction, modelComposition, skipCache = false, retryStrategy) {
|
|
100
102
|
var _a, _b, _c;
|
|
101
|
-
|
|
103
|
+
const strategy = retryStrategy !== null && retryStrategy !== void 0 ? retryStrategy : this.retryStrategy;
|
|
104
|
+
let command = yield this.predictCommand(instruction, modelComposition, skipCache);
|
|
102
105
|
/* eslint-disable no-await-in-loop */
|
|
103
|
-
for (let k = 0; k <
|
|
106
|
+
for (let k = 0; k < strategy.retryCount; k += 1) {
|
|
104
107
|
if (command.code === ControlCommandCode.OK) {
|
|
105
108
|
return command;
|
|
106
109
|
}
|
|
107
|
-
const msUntilRetry =
|
|
108
|
-
logger.debug(`Wait ${msUntilRetry} and retry predicting command...`);
|
|
110
|
+
const msUntilRetry = strategy.getDelay(k + 1);
|
|
111
|
+
logger.debug(`Wait ${msUntilRetry} and retry ${k + 1}/${strategy.retryCount} predicting command...`);
|
|
109
112
|
yield delay(msUntilRetry);
|
|
110
|
-
command = yield this.predictCommand(instruction, modelComposition, new ControlCommandError((_c = (_b = (_a = command.actions) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : ''));
|
|
113
|
+
command = yield this.predictCommand(instruction, modelComposition, skipCache, new ControlCommandError((_c = (_b = (_a = command.actions) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : ''));
|
|
111
114
|
}
|
|
112
115
|
/* eslint-enable no-await-in-loop */
|
|
113
116
|
return command;
|
|
@@ -117,11 +120,11 @@ export class ExecutionRuntime {
|
|
|
117
120
|
return this.stepReporter.config.withScreenshots === 'begin'
|
|
118
121
|
|| this.stepReporter.config.withScreenshots === 'always';
|
|
119
122
|
}
|
|
120
|
-
isImageRequired(instruction) {
|
|
123
|
+
isImageRequired(instruction, customElements) {
|
|
121
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
122
125
|
if (this.isImageRequiredByConfig())
|
|
123
126
|
return Promise.resolve(true);
|
|
124
|
-
return this.inferenceClient.isImageRequired(instruction);
|
|
127
|
+
return this.inferenceClient.isImageRequired(instruction, customElements);
|
|
125
128
|
});
|
|
126
129
|
}
|
|
127
130
|
isAnnotationRequired() {
|
|
@@ -136,8 +139,9 @@ export class ExecutionRuntime {
|
|
|
136
139
|
}
|
|
137
140
|
buildSnapshot(instruction) {
|
|
138
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
var _a;
|
|
139
143
|
const createdAt = new Date();
|
|
140
|
-
const screenshot = (yield this.isImageRequired(instruction))
|
|
144
|
+
const screenshot = (yield this.isImageRequired(instruction.value, (_a = instruction.customElements) !== null && _a !== void 0 ? _a : []))
|
|
141
145
|
? yield this.getScreenshot() : undefined;
|
|
142
146
|
const annotation = this.isAnnotationRequired() ? yield this.annotateImage() : undefined;
|
|
143
147
|
return {
|
|
@@ -147,14 +151,14 @@ export class ExecutionRuntime {
|
|
|
147
151
|
};
|
|
148
152
|
});
|
|
149
153
|
}
|
|
150
|
-
predictCommand(
|
|
151
|
-
return __awaiter(this,
|
|
152
|
-
const snapshot = yield this.buildSnapshot(instruction
|
|
154
|
+
predictCommand(instruction_1, modelComposition_1) {
|
|
155
|
+
return __awaiter(this, arguments, void 0, function* (instruction, modelComposition, skipCache = false, retryError) {
|
|
156
|
+
const snapshot = yield this.buildSnapshot(instruction);
|
|
153
157
|
if (retryError !== undefined)
|
|
154
158
|
this.stepReporter.onStepRetry(snapshot, retryError);
|
|
155
159
|
else
|
|
156
160
|
this.stepReporter.onStepBegin(snapshot);
|
|
157
|
-
const controlCommand = yield this.inferenceClient.predictControlCommand(instruction.value, modelComposition, instruction.customElements, snapshot.screenshot);
|
|
161
|
+
const controlCommand = yield this.inferenceClient.predictControlCommand(instruction.value, modelComposition, instruction.customElements, snapshot.screenshot, skipCache);
|
|
158
162
|
if (instruction.secretText !== undefined) {
|
|
159
163
|
controlCommand.setTextToBeTyped(instruction.secretText);
|
|
160
164
|
}
|
|
@@ -6,21 +6,23 @@ import { Annotation } from '../core/annotation/annotation';
|
|
|
6
6
|
import { DetectedElement } from '../core/model/annotation-result/detected-element';
|
|
7
7
|
import { VQAInferenceResponseBody } from '../core/inference-response/inference-response';
|
|
8
8
|
import { ModelCompositionBranch } from './model-composition-branch';
|
|
9
|
+
import { CacheInterface } from '../core/cache';
|
|
9
10
|
export declare class InferenceClient {
|
|
10
11
|
private readonly baseUrl;
|
|
11
12
|
private readonly httpClient;
|
|
13
|
+
readonly cacheManager: CacheInterface;
|
|
12
14
|
private readonly resize?;
|
|
13
15
|
readonly workspaceId?: string | undefined;
|
|
14
16
|
readonly modelComposition?: ModelCompositionBranch[] | undefined;
|
|
15
17
|
private readonly apiVersion;
|
|
16
18
|
private urls;
|
|
17
|
-
constructor(baseUrl: string, httpClient: HttpClientGot, resize?: number | undefined, workspaceId?: string | undefined, modelComposition?: ModelCompositionBranch[] | undefined, apiVersion?: string);
|
|
18
|
-
isImageRequired(instruction: string): Promise<boolean>;
|
|
19
|
+
constructor(baseUrl: string, httpClient: HttpClientGot, cacheManager: CacheInterface, resize?: number | undefined, workspaceId?: string | undefined, modelComposition?: ModelCompositionBranch[] | undefined, apiVersion?: string);
|
|
20
|
+
isImageRequired(instruction: string, customElements: CustomElement[]): Promise<boolean>;
|
|
19
21
|
private resizeIfNeeded;
|
|
20
22
|
inference(customElements?: CustomElement[], image?: string, instruction?: string, modelComposition?: ModelCompositionBranch[]): Promise<ControlCommand | Annotation>;
|
|
21
23
|
vqaInference(image: string, prompt: string, config?: object): Promise<VQAInferenceResponseBody>;
|
|
22
24
|
private static logMetaInformation;
|
|
23
|
-
predictControlCommand(instruction: string, modelComposition: ModelCompositionBranch[], customElements?: CustomElement[], image?: string): Promise<ControlCommand>;
|
|
25
|
+
predictControlCommand(instruction: string, modelComposition: ModelCompositionBranch[], customElements?: CustomElement[], image?: string, skipCache?: boolean): Promise<ControlCommand>;
|
|
24
26
|
getDetectedElements(instruction: string, image: string, customElements?: CustomElement[]): Promise<DetectedElement[]>;
|
|
25
27
|
predictImageAnnotation(image: string, customElements?: CustomElement[]): Promise<Annotation>;
|
|
26
28
|
predictVQAAnswer(prompt: string, image: string, config?: object): Promise<any>;
|
|
@@ -14,10 +14,12 @@ import { resizeBase64ImageWithSameRatio } from '../utils/transformations';
|
|
|
14
14
|
import { InferenceResponseError } from './inference-response-error';
|
|
15
15
|
import { ConfigurationError } from './config-error';
|
|
16
16
|
import { logger } from '../lib/logger';
|
|
17
|
+
import { ControlCommandCode } from '../core/ui-control-commands/control-command-code';
|
|
17
18
|
export class InferenceClient {
|
|
18
|
-
constructor(baseUrl, httpClient, resize, workspaceId, modelComposition, apiVersion = 'v1') {
|
|
19
|
+
constructor(baseUrl, httpClient, cacheManager, resize, workspaceId, modelComposition, apiVersion = 'v1') {
|
|
19
20
|
this.baseUrl = baseUrl;
|
|
20
21
|
this.httpClient = httpClient;
|
|
22
|
+
this.cacheManager = cacheManager;
|
|
21
23
|
this.resize = resize;
|
|
22
24
|
this.workspaceId = workspaceId;
|
|
23
25
|
this.modelComposition = modelComposition;
|
|
@@ -38,8 +40,13 @@ export class InferenceClient {
|
|
|
38
40
|
}
|
|
39
41
|
this.resize = this.resize ? Math.ceil(this.resize) : this.resize;
|
|
40
42
|
}
|
|
41
|
-
isImageRequired(instruction) {
|
|
43
|
+
isImageRequired(instruction, customElements) {
|
|
42
44
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const cachedImageRequired = this.cacheManager.isImageRequired(instruction, customElements);
|
|
46
|
+
if (cachedImageRequired !== undefined) {
|
|
47
|
+
logger.debug(`Cache hit for image required: '${instruction}'.`);
|
|
48
|
+
return Promise.resolve(cachedImageRequired);
|
|
49
|
+
}
|
|
43
50
|
const response = yield this.httpClient.post(this.urls.isImageRequired, {
|
|
44
51
|
instruction,
|
|
45
52
|
});
|
|
@@ -90,11 +97,23 @@ export class InferenceClient {
|
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
99
|
predictControlCommand(instruction_1, modelComposition_1) {
|
|
93
|
-
return __awaiter(this, arguments, void 0, function* (instruction, modelComposition, customElements = [], image) {
|
|
100
|
+
return __awaiter(this, arguments, void 0, function* (instruction, modelComposition, customElements = [], image, skipCache = false) {
|
|
101
|
+
if (!skipCache) {
|
|
102
|
+
const cachedControlCommand = yield this.cacheManager.getCachedControlCommand(instruction, customElements, image);
|
|
103
|
+
if (cachedControlCommand !== undefined) {
|
|
104
|
+
logger.debug(`Cache hit for instruction: '${instruction}'.`);
|
|
105
|
+
return Promise.resolve(cachedControlCommand);
|
|
106
|
+
}
|
|
107
|
+
logger.debug(`Cache miss for instruction: '${instruction}'.`);
|
|
108
|
+
}
|
|
94
109
|
const inferenceResponse = yield this.inference(customElements, image, instruction, modelComposition);
|
|
95
110
|
if (!(inferenceResponse instanceof ControlCommand)) {
|
|
96
111
|
throw new InferenceResponseError('Internal Error. Can not execute command');
|
|
97
112
|
}
|
|
113
|
+
if (!skipCache && inferenceResponse.code === ControlCommandCode.OK) {
|
|
114
|
+
yield this.cacheManager.addCacheEntryFromControlCommand(instruction, inferenceResponse, customElements, image);
|
|
115
|
+
logger.debug(`Cache added for instruction: '${instruction}'`);
|
|
116
|
+
}
|
|
98
117
|
return inferenceResponse;
|
|
99
118
|
});
|
|
100
119
|
}
|
|
@@ -17,6 +17,7 @@ import { ExecutionRuntime } from './execution-runtime';
|
|
|
17
17
|
import { StepReporter } from '../core/reporting';
|
|
18
18
|
import { readCredentials } from './read-credentials';
|
|
19
19
|
import { LinearRetryStrategy } from './retry-strategies/linear-retry-strategy';
|
|
20
|
+
import { CacheManager, DummyCacheManager } from '../core/cache';
|
|
20
21
|
export class UiControlClientDependencyBuilder {
|
|
21
22
|
static buildHttpClient(clientArgs) {
|
|
22
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -31,7 +32,11 @@ export class UiControlClientDependencyBuilder {
|
|
|
31
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
33
|
var _a;
|
|
33
34
|
const httpClient = yield UiControlClientDependencyBuilder.buildHttpClient(clientArgs);
|
|
34
|
-
|
|
35
|
+
let cacheManager = new DummyCacheManager();
|
|
36
|
+
if (clientArgs.cacheConfig) {
|
|
37
|
+
cacheManager = new CacheManager(clientArgs.cacheConfig);
|
|
38
|
+
}
|
|
39
|
+
return new InferenceClient(clientArgs.inferenceServerUrl, httpClient, cacheManager, clientArgs.resize, (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId, clientArgs.modelComposition, clientArgs.inferenceServerApiVersion);
|
|
35
40
|
});
|
|
36
41
|
}
|
|
37
42
|
static buildUiControllerClient(clientArgs) {
|
|
@@ -5,6 +5,7 @@ import { AnnotationRequest } from '../core/model/annotation-result/annotation-in
|
|
|
5
5
|
import { DetectedElement } from '../core/model/annotation-result/detected-element';
|
|
6
6
|
import { ClientArgs } from './ui-controller-client-interface';
|
|
7
7
|
import { ModelCompositionBranch } from './model-composition-branch';
|
|
8
|
+
import { RetryStrategy } from './retry-strategies';
|
|
8
9
|
import { AskUIAgent, AgentHistory, ActOptions } from '../core/models/anthropic';
|
|
9
10
|
export type RelationsForConvenienceMethods = 'nearestTo' | 'leftOf' | 'above' | 'rightOf' | 'below' | 'contains';
|
|
10
11
|
export type TextMatchingOption = 'similar' | 'exact' | 'regex';
|
|
@@ -62,7 +63,7 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
62
63
|
private escapeSeparatorString;
|
|
63
64
|
private buildInstruction;
|
|
64
65
|
private getAIElementsByNames;
|
|
65
|
-
fluentCommandExecutor(instructionString: string, modelComposition: ModelCompositionBranch[], context?: CommandExecutorContext): Promise<void>;
|
|
66
|
+
fluentCommandExecutor(instructionString: string, modelComposition: ModelCompositionBranch[], context?: CommandExecutorContext, skipCache?: boolean, retryStrategy?: RetryStrategy): Promise<void>;
|
|
66
67
|
getterExecutor(instruction: string, context?: CommandExecutorContext): Promise<DetectedElement[]>;
|
|
67
68
|
/**
|
|
68
69
|
* Takes a prompt that contains a question you want to be answered
|
|
@@ -15,6 +15,7 @@ import { logger } from '../lib/logger';
|
|
|
15
15
|
import { UiControlClientDependencyBuilder } from './ui-control-client-dependency-builder';
|
|
16
16
|
import { AIElementCollection } from '../core/ai-element/ai-element-collection';
|
|
17
17
|
import { NoRetryStrategy } from './retry-strategies';
|
|
18
|
+
import { ControlCommandError } from './control-command-error';
|
|
18
19
|
import { AskUIAgent } from '../core/models/anthropic';
|
|
19
20
|
import { AskUIGetAskUIElementTool, AskUIListAIElementTool } from '../core/models/anthropic/tools/askui-api-tools';
|
|
20
21
|
export class UiControlClient extends ApiCommands {
|
|
@@ -157,7 +158,7 @@ export class UiControlClient extends ApiCommands {
|
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
160
|
fluentCommandExecutor(instructionString_1, modelComposition_1) {
|
|
160
|
-
return __awaiter(this, arguments, void 0, function* (instructionString, modelComposition, context = { customElementsJson: [], aiElementNames: [] }) {
|
|
161
|
+
return __awaiter(this, arguments, void 0, function* (instructionString, modelComposition, context = { customElementsJson: [], aiElementNames: [] }, skipCache = false, retryStrategy) {
|
|
161
162
|
const aiElements = yield this.getAIElementsByNames(context.aiElementNames);
|
|
162
163
|
const instruction = yield this.buildInstruction(instructionString, [
|
|
163
164
|
...context.customElementsJson,
|
|
@@ -166,7 +167,7 @@ export class UiControlClient extends ApiCommands {
|
|
|
166
167
|
logger.debug(instruction);
|
|
167
168
|
try {
|
|
168
169
|
this.stepReporter.resetStep(instruction);
|
|
169
|
-
yield this.executionRuntime.executeInstruction(instruction, modelComposition);
|
|
170
|
+
yield this.executionRuntime.executeInstruction(instruction, modelComposition, skipCache, retryStrategy);
|
|
170
171
|
yield this.afterCommandExecution(instruction);
|
|
171
172
|
return yield Promise.resolve();
|
|
172
173
|
}
|
|
@@ -450,18 +451,34 @@ export class UiControlClient extends ApiCommands {
|
|
|
450
451
|
*/
|
|
451
452
|
waitUntil(AskUICommand_1) {
|
|
452
453
|
return __awaiter(this, arguments, void 0, function* (AskUICommand, maxTry = 5, waitTime = 2000) {
|
|
454
|
+
logger.debug(`waitUntil: Starting with maxTry=${maxTry}, waitTime=${waitTime}ms, retryStrategy=${this.executionRuntime.retryStrategy.constructor.name}`);
|
|
453
455
|
const userDefinedStrategy = this.executionRuntime.retryStrategy;
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
456
|
+
this.executionRuntime.retryStrategy = new NoRetryStrategy();
|
|
457
|
+
const attempt = (retriesLeft) => __awaiter(this, void 0, void 0, function* () {
|
|
458
|
+
const attemptNumber = maxTry - retriesLeft;
|
|
459
|
+
logger.debug(`waitUntil: Attempt ${attemptNumber}/${maxTry} (${retriesLeft} retries remaining)`);
|
|
460
|
+
try {
|
|
461
|
+
yield AskUICommand.exec();
|
|
462
|
+
logger.debug(`waitUntil: Command succeeded on attempt ${attemptNumber}/${maxTry}`);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
catch (error) {
|
|
466
|
+
if (error instanceof ControlCommandError && retriesLeft > 0) {
|
|
467
|
+
logger.debug(`waitUntil: ControlCommandError on attempt ${attemptNumber}/${maxTry}, waiting ${waitTime}ms before retry.`, error);
|
|
468
|
+
yield this.waitFor(waitTime).exec();
|
|
469
|
+
yield attempt(retriesLeft - 1);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const errorName = error instanceof Error ? error.name : 'Error';
|
|
473
|
+
logger.debug(`waitUntil: ${errorName} on attempt ${attemptNumber}/${maxTry}, no retries remaining.`, error);
|
|
461
474
|
throw error;
|
|
462
475
|
}
|
|
463
|
-
|
|
464
|
-
|
|
476
|
+
});
|
|
477
|
+
try {
|
|
478
|
+
yield attempt(maxTry - 1);
|
|
479
|
+
}
|
|
480
|
+
finally {
|
|
481
|
+
this.executionRuntime.retryStrategy = userDefinedStrategy;
|
|
465
482
|
}
|
|
466
483
|
});
|
|
467
484
|
}
|
|
@@ -5,6 +5,7 @@ import { Reporter } from '../core/reporting';
|
|
|
5
5
|
import { Context } from './context';
|
|
6
6
|
import { RetryStrategy } from './retry-strategies/retry-strategy';
|
|
7
7
|
import { AIElementArgs } from '../core/ai-element/ai-elements-args';
|
|
8
|
+
import { CacheConfig } from '../core/cache';
|
|
8
9
|
/**
|
|
9
10
|
* Context object to provide additional information about the context of (test) automation.
|
|
10
11
|
*
|
|
@@ -63,6 +64,7 @@ export interface ClientArgs {
|
|
|
63
64
|
readonly inferenceServerApiVersion?: string;
|
|
64
65
|
readonly retryStrategy?: RetryStrategy;
|
|
65
66
|
readonly aiElementArgs?: AIElementArgs;
|
|
67
|
+
readonly cacheConfig?: CacheConfig;
|
|
66
68
|
}
|
|
67
69
|
export interface ClientArgsWithDefaults extends ClientArgs {
|
|
68
70
|
readonly uiControllerUrl: string;
|
|
@@ -12,5 +12,7 @@ export declare class Base64Image {
|
|
|
12
12
|
getInfo(): Promise<sharp.OutputInfo>;
|
|
13
13
|
resizeToFitInto(dimension: number): Promise<Base64Image>;
|
|
14
14
|
resizeWithSameAspectRatio(width: number, height: number): Promise<Base64Image>;
|
|
15
|
+
cropRegion(x: number, y: number, croppedWidth: number, croppedHeight: number): Promise<Base64Image>;
|
|
15
16
|
toString(withPrefix?: boolean): string;
|
|
17
|
+
toBuffer(): Buffer;
|
|
16
18
|
}
|
|
@@ -61,11 +61,12 @@ export class Base64Image {
|
|
|
61
61
|
resizeToFitInto(dimension) {
|
|
62
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
63
|
const { width, height } = yield this.getInfo();
|
|
64
|
+
const roundedDimension = Math.round(dimension);
|
|
64
65
|
const buffer = yield (yield this.getSharp())
|
|
65
66
|
.resize({
|
|
66
67
|
fit: 'contain',
|
|
67
|
-
height: height > width ?
|
|
68
|
-
width: width >= height ?
|
|
68
|
+
height: height > width ? roundedDimension : undefined,
|
|
69
|
+
width: width >= height ? roundedDimension : undefined,
|
|
69
70
|
})
|
|
70
71
|
.toBuffer();
|
|
71
72
|
return Base64Image.fromBuffer(buffer);
|
|
@@ -73,11 +74,30 @@ export class Base64Image {
|
|
|
73
74
|
}
|
|
74
75
|
resizeWithSameAspectRatio(width, height) {
|
|
75
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const roundedWidth = Math.round(width);
|
|
78
|
+
const roundedHeight = Math.round(height);
|
|
76
79
|
const buffer = yield (yield this.getSharp())
|
|
77
80
|
.resize({
|
|
78
81
|
fit: 'contain',
|
|
79
|
-
height,
|
|
80
|
-
width,
|
|
82
|
+
height: roundedHeight,
|
|
83
|
+
width: roundedWidth,
|
|
84
|
+
})
|
|
85
|
+
.toBuffer();
|
|
86
|
+
return Base64Image.fromBuffer(buffer);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
cropRegion(x, y, croppedWidth, croppedHeight) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
const roundedX = Math.round(x);
|
|
92
|
+
const roundedY = Math.round(y);
|
|
93
|
+
const roundedCroppedWidth = Math.round(croppedWidth);
|
|
94
|
+
const roundedCroppedHeight = Math.round(croppedHeight);
|
|
95
|
+
const buffer = yield (yield this.getSharp())
|
|
96
|
+
.extract({
|
|
97
|
+
height: roundedCroppedHeight,
|
|
98
|
+
left: roundedX,
|
|
99
|
+
top: roundedY,
|
|
100
|
+
width: roundedCroppedWidth,
|
|
81
101
|
})
|
|
82
102
|
.toBuffer();
|
|
83
103
|
return Base64Image.fromBuffer(buffer);
|
|
@@ -89,5 +109,8 @@ export class Base64Image {
|
|
|
89
109
|
}
|
|
90
110
|
return this.buffer.toString('base64');
|
|
91
111
|
}
|
|
112
|
+
toBuffer() {
|
|
113
|
+
return this.buffer;
|
|
114
|
+
}
|
|
92
115
|
}
|
|
93
116
|
Base64Image.strPrefix = 'data:image/png;base64,';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "askui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "askui GmbH <info@askui.com> (http://www.askui.com/)",
|
|
6
6
|
"description": "Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on",
|