askui 0.4.0 → 0.6.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/execution/config-error.d.ts +2 -0
- package/dist/cjs/execution/config-error.js +6 -0
- package/dist/cjs/execution/dsl.d.ts +387 -2
- package/dist/cjs/execution/dsl.js +405 -2
- package/dist/cjs/execution/inference-client.d.ts +2 -1
- package/dist/cjs/execution/inference-client.js +9 -3
- package/dist/cjs/execution/ui-control-client.js +4 -2
- package/dist/cjs/execution/ui-controller-client-interface.d.ts +13 -0
- package/dist/cjs/lib/copy-example-project.js +40 -4
- package/dist/cjs/lib/download-binaries.d.ts +7 -1
- package/dist/cjs/lib/download-binaries.js +2 -2
- package/dist/cjs/lib/ui-controller-args.d.ts +4 -0
- package/dist/cjs/lib/ui-controller-facade.js +4 -3
- package/dist/cjs/shared/proxy-agent-args.d.ts +35 -0
- package/dist/cjs/shared/proxy-agent-args.js +2 -0
- package/dist/cjs/utils/http/http-client-got.d.ts +11 -1
- package/dist/cjs/utils/http/http-client-got.js +5 -3
- package/dist/cjs/utils/proxy/proxy-builder.d.ts +4 -0
- package/dist/cjs/utils/proxy/proxy-builder.js +67 -0
- package/dist/esm/execution/config-error.d.ts +2 -0
- package/dist/esm/execution/config-error.js +2 -0
- package/dist/esm/execution/dsl.d.ts +387 -2
- package/dist/esm/execution/dsl.js +405 -2
- package/dist/esm/execution/inference-client.d.ts +2 -1
- package/dist/esm/execution/inference-client.js +9 -3
- package/dist/esm/execution/ui-control-client.js +4 -2
- package/dist/esm/execution/ui-controller-client-interface.d.ts +13 -0
- package/dist/esm/lib/copy-example-project.js +40 -4
- package/dist/esm/lib/download-binaries.d.ts +7 -1
- package/dist/esm/lib/download-binaries.js +2 -2
- package/dist/esm/lib/ui-controller-args.d.ts +4 -0
- package/dist/esm/lib/ui-controller-facade.js +4 -3
- package/dist/esm/shared/proxy-agent-args.d.ts +35 -0
- package/dist/esm/shared/proxy-agent-args.js +1 -0
- package/dist/esm/utils/http/http-client-got.d.ts +11 -1
- package/dist/esm/utils/http/http-client-got.js +5 -3
- package/dist/esm/utils/proxy/proxy-builder.d.ts +4 -0
- package/dist/esm/utils/proxy/proxy-builder.js +43 -0
- package/dist/example_projects_templates/typescript_jest/test/helper/jest.setup.ts +8 -3
- package/dist/example_projects_templates/typescript_jest/test/my-first-askui-test-suite.test.ts +5 -0
- package/package.json +5 -2
|
@@ -794,6 +794,120 @@ export class FluentFilters extends FluentBase {
|
|
|
794
794
|
}
|
|
795
795
|
// Relations
|
|
796
796
|
export class FluentFiltersOrRelations extends FluentFilters {
|
|
797
|
+
/**
|
|
798
|
+
* Logic or operator
|
|
799
|
+
*
|
|
800
|
+
* **Examples:**
|
|
801
|
+
* ```text
|
|
802
|
+
* scene 1
|
|
803
|
+
* -------------- ---------------
|
|
804
|
+
* | button | | icon |
|
|
805
|
+
* -------------- ---------------
|
|
806
|
+
*
|
|
807
|
+
* scene 2
|
|
808
|
+
* -------------- ---------------
|
|
809
|
+
* | button | | text |
|
|
810
|
+
* -------------- ---------------
|
|
811
|
+
*
|
|
812
|
+
* ```
|
|
813
|
+
* In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
|
|
814
|
+
* You can use **the `or()` relation**, so your teststep is valid for both scenes
|
|
815
|
+
* ```typescript
|
|
816
|
+
* const button = await aui.get().button().rightOf().icon().or().text().exec();
|
|
817
|
+
* console.log(button);
|
|
818
|
+
* ```
|
|
819
|
+
* Returns the same button for both cases
|
|
820
|
+
* ```text
|
|
821
|
+
* console output: [
|
|
822
|
+
* DetectedElement {
|
|
823
|
+
* name: 'BUTTON',
|
|
824
|
+
* text: 'button',
|
|
825
|
+
* colors: [ 'red', 'black', 'red' ],
|
|
826
|
+
* bndbox: BoundingBox {
|
|
827
|
+
* xmin: 900,
|
|
828
|
+
* ymin: 910,
|
|
829
|
+
* xmax: 920,
|
|
830
|
+
* ymax: 930
|
|
831
|
+
* }
|
|
832
|
+
* }
|
|
833
|
+
* ]
|
|
834
|
+
* ```
|
|
835
|
+
*
|
|
836
|
+
* @return {FluentFilters}
|
|
837
|
+
*/
|
|
838
|
+
or() {
|
|
839
|
+
this._textStr = 'or';
|
|
840
|
+
return new FluentFilters(this);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Logic and operator
|
|
844
|
+
*
|
|
845
|
+
* **Examples:**
|
|
846
|
+
* ```text
|
|
847
|
+
* example scene:
|
|
848
|
+
* -------------------------- --------------------------
|
|
849
|
+
* | icon user colored black | | icon user colored red |
|
|
850
|
+
* -------------------------- --------------------------
|
|
851
|
+
* ```
|
|
852
|
+
* ```typescript
|
|
853
|
+
* const icons = await aui.get().icon().withText('user').exec();
|
|
854
|
+
* console.log(icons);
|
|
855
|
+
* ```
|
|
856
|
+
* Using only the filter withText, the get command will return both icons because they share the same text
|
|
857
|
+
* ```text
|
|
858
|
+
* console output: [
|
|
859
|
+
* DetectedElement {
|
|
860
|
+
* name: 'ICON',
|
|
861
|
+
* text: 'user',
|
|
862
|
+
* colors: [ 'black', 'black', 'black' ],
|
|
863
|
+
* bndbox: BoundingBox {
|
|
864
|
+
* xmin: 1000,
|
|
865
|
+
* ymin: 1010,
|
|
866
|
+
* xmax: 1020,
|
|
867
|
+
* ymax: 1030
|
|
868
|
+
* }
|
|
869
|
+
* },
|
|
870
|
+
* DetectedElement {
|
|
871
|
+
* name: 'ICON',
|
|
872
|
+
* text: 'user',
|
|
873
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
874
|
+
* bndbox: BoundingBox {
|
|
875
|
+
* xmin: 900,
|
|
876
|
+
* ymin: 910,
|
|
877
|
+
* xmax: 920,
|
|
878
|
+
* ymax: 930
|
|
879
|
+
* }
|
|
880
|
+
* }
|
|
881
|
+
* ]
|
|
882
|
+
* ```
|
|
883
|
+
* You can combine filters with **the `and()` relation** and specify exactly which icon you want
|
|
884
|
+
* ```typescript
|
|
885
|
+
* const icons = await aui.get().icon().withText('user').and().colored('red').exec()
|
|
886
|
+
* console.log(icons)
|
|
887
|
+
* ```
|
|
888
|
+
* The get command returns only the red icon although both icons have the same text
|
|
889
|
+
* ```text
|
|
890
|
+
* console output: [
|
|
891
|
+
* DetectedElement {
|
|
892
|
+
* name: 'ICON',
|
|
893
|
+
* text: 'user',
|
|
894
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
895
|
+
* bndbox: BoundingBox {
|
|
896
|
+
* xmin: 900,
|
|
897
|
+
* ymin: 910,
|
|
898
|
+
* xmax: 920,
|
|
899
|
+
* ymax: 930
|
|
900
|
+
* }
|
|
901
|
+
* }
|
|
902
|
+
* ]
|
|
903
|
+
* ```
|
|
904
|
+
*
|
|
905
|
+
* @return {FluentFilters}
|
|
906
|
+
*/
|
|
907
|
+
and() {
|
|
908
|
+
this._textStr = 'and';
|
|
909
|
+
return new FluentFilters(this);
|
|
910
|
+
}
|
|
797
911
|
/**
|
|
798
912
|
* Filters for an element inside another element.
|
|
799
913
|
*
|
|
@@ -1704,6 +1818,120 @@ export class FluentFiltersCondition extends FluentBase {
|
|
|
1704
1818
|
}
|
|
1705
1819
|
// Relations
|
|
1706
1820
|
export class FluentFiltersOrRelationsCondition extends FluentFiltersCondition {
|
|
1821
|
+
/**
|
|
1822
|
+
* Logic or operator
|
|
1823
|
+
*
|
|
1824
|
+
* **Examples:**
|
|
1825
|
+
* ```text
|
|
1826
|
+
* scene 1
|
|
1827
|
+
* -------------- ---------------
|
|
1828
|
+
* | button | | icon |
|
|
1829
|
+
* -------------- ---------------
|
|
1830
|
+
*
|
|
1831
|
+
* scene 2
|
|
1832
|
+
* -------------- ---------------
|
|
1833
|
+
* | button | | text |
|
|
1834
|
+
* -------------- ---------------
|
|
1835
|
+
*
|
|
1836
|
+
* ```
|
|
1837
|
+
* In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
|
|
1838
|
+
* You can use **the `or()` relation**, so your teststep is valid for both scenes
|
|
1839
|
+
* ```typescript
|
|
1840
|
+
* const button = await aui.get().button().rightOf().icon().or().text().exec();
|
|
1841
|
+
* console.log(button);
|
|
1842
|
+
* ```
|
|
1843
|
+
* Returns the same button for both cases
|
|
1844
|
+
* ```text
|
|
1845
|
+
* console output: [
|
|
1846
|
+
* DetectedElement {
|
|
1847
|
+
* name: 'BUTTON',
|
|
1848
|
+
* text: 'button',
|
|
1849
|
+
* colors: [ 'red', 'black', 'red' ],
|
|
1850
|
+
* bndbox: BoundingBox {
|
|
1851
|
+
* xmin: 900,
|
|
1852
|
+
* ymin: 910,
|
|
1853
|
+
* xmax: 920,
|
|
1854
|
+
* ymax: 930
|
|
1855
|
+
* }
|
|
1856
|
+
* }
|
|
1857
|
+
* ]
|
|
1858
|
+
* ```
|
|
1859
|
+
*
|
|
1860
|
+
* @return {FluentFiltersCondition}
|
|
1861
|
+
*/
|
|
1862
|
+
or() {
|
|
1863
|
+
this._textStr = 'or';
|
|
1864
|
+
return new FluentFiltersCondition(this);
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Logic and operator
|
|
1868
|
+
*
|
|
1869
|
+
* **Examples:**
|
|
1870
|
+
* ```text
|
|
1871
|
+
* example scene:
|
|
1872
|
+
* -------------------------- --------------------------
|
|
1873
|
+
* | icon user colored black | | icon user colored red |
|
|
1874
|
+
* -------------------------- --------------------------
|
|
1875
|
+
* ```
|
|
1876
|
+
* ```typescript
|
|
1877
|
+
* const icons = await aui.get().icon().withText('user').exec();
|
|
1878
|
+
* console.log(icons);
|
|
1879
|
+
* ```
|
|
1880
|
+
* Using only the filter withText, the get command will return both icons because they share the same text
|
|
1881
|
+
* ```text
|
|
1882
|
+
* console output: [
|
|
1883
|
+
* DetectedElement {
|
|
1884
|
+
* name: 'ICON',
|
|
1885
|
+
* text: 'user',
|
|
1886
|
+
* colors: [ 'black', 'black', 'black' ],
|
|
1887
|
+
* bndbox: BoundingBox {
|
|
1888
|
+
* xmin: 1000,
|
|
1889
|
+
* ymin: 1010,
|
|
1890
|
+
* xmax: 1020,
|
|
1891
|
+
* ymax: 1030
|
|
1892
|
+
* }
|
|
1893
|
+
* },
|
|
1894
|
+
* DetectedElement {
|
|
1895
|
+
* name: 'ICON',
|
|
1896
|
+
* text: 'user',
|
|
1897
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
1898
|
+
* bndbox: BoundingBox {
|
|
1899
|
+
* xmin: 900,
|
|
1900
|
+
* ymin: 910,
|
|
1901
|
+
* xmax: 920,
|
|
1902
|
+
* ymax: 930
|
|
1903
|
+
* }
|
|
1904
|
+
* }
|
|
1905
|
+
* ]
|
|
1906
|
+
* ```
|
|
1907
|
+
* You can combine filters with **the `and()` relation** and specify exactly which icon you want
|
|
1908
|
+
* ```typescript
|
|
1909
|
+
* const icons = await aui.get().icon().withText('user').and().colored('red').exec()
|
|
1910
|
+
* console.log(icons)
|
|
1911
|
+
* ```
|
|
1912
|
+
* The get command returns only the red icon although both icons have the same text
|
|
1913
|
+
* ```text
|
|
1914
|
+
* console output: [
|
|
1915
|
+
* DetectedElement {
|
|
1916
|
+
* name: 'ICON',
|
|
1917
|
+
* text: 'user',
|
|
1918
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
1919
|
+
* bndbox: BoundingBox {
|
|
1920
|
+
* xmin: 900,
|
|
1921
|
+
* ymin: 910,
|
|
1922
|
+
* xmax: 920,
|
|
1923
|
+
* ymax: 930
|
|
1924
|
+
* }
|
|
1925
|
+
* }
|
|
1926
|
+
* ]
|
|
1927
|
+
* ```
|
|
1928
|
+
*
|
|
1929
|
+
* @return {FluentFiltersCondition}
|
|
1930
|
+
*/
|
|
1931
|
+
and() {
|
|
1932
|
+
this._textStr = 'and';
|
|
1933
|
+
return new FluentFiltersCondition(this);
|
|
1934
|
+
}
|
|
1707
1935
|
/**
|
|
1708
1936
|
* Filters for an element inside another element.
|
|
1709
1937
|
*
|
|
@@ -2922,6 +3150,120 @@ export class FluentFiltersGetter extends FluentBase {
|
|
|
2922
3150
|
}
|
|
2923
3151
|
// Relations
|
|
2924
3152
|
export class FluentFiltersOrRelationsGetter extends FluentFiltersGetter {
|
|
3153
|
+
/**
|
|
3154
|
+
* Logic or operator
|
|
3155
|
+
*
|
|
3156
|
+
* **Examples:**
|
|
3157
|
+
* ```text
|
|
3158
|
+
* scene 1
|
|
3159
|
+
* -------------- ---------------
|
|
3160
|
+
* | button | | icon |
|
|
3161
|
+
* -------------- ---------------
|
|
3162
|
+
*
|
|
3163
|
+
* scene 2
|
|
3164
|
+
* -------------- ---------------
|
|
3165
|
+
* | button | | text |
|
|
3166
|
+
* -------------- ---------------
|
|
3167
|
+
*
|
|
3168
|
+
* ```
|
|
3169
|
+
* In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
|
|
3170
|
+
* You can use **the `or()` relation**, so your teststep is valid for both scenes
|
|
3171
|
+
* ```typescript
|
|
3172
|
+
* const button = await aui.get().button().rightOf().icon().or().text().exec();
|
|
3173
|
+
* console.log(button);
|
|
3174
|
+
* ```
|
|
3175
|
+
* Returns the same button for both cases
|
|
3176
|
+
* ```text
|
|
3177
|
+
* console output: [
|
|
3178
|
+
* DetectedElement {
|
|
3179
|
+
* name: 'BUTTON',
|
|
3180
|
+
* text: 'button',
|
|
3181
|
+
* colors: [ 'red', 'black', 'red' ],
|
|
3182
|
+
* bndbox: BoundingBox {
|
|
3183
|
+
* xmin: 900,
|
|
3184
|
+
* ymin: 910,
|
|
3185
|
+
* xmax: 920,
|
|
3186
|
+
* ymax: 930
|
|
3187
|
+
* }
|
|
3188
|
+
* }
|
|
3189
|
+
* ]
|
|
3190
|
+
* ```
|
|
3191
|
+
*
|
|
3192
|
+
* @return {FluentFiltersGetter}
|
|
3193
|
+
*/
|
|
3194
|
+
or() {
|
|
3195
|
+
this._textStr = 'or';
|
|
3196
|
+
return new FluentFiltersGetter(this);
|
|
3197
|
+
}
|
|
3198
|
+
/**
|
|
3199
|
+
* Logic and operator
|
|
3200
|
+
*
|
|
3201
|
+
* **Examples:**
|
|
3202
|
+
* ```text
|
|
3203
|
+
* example scene:
|
|
3204
|
+
* -------------------------- --------------------------
|
|
3205
|
+
* | icon user colored black | | icon user colored red |
|
|
3206
|
+
* -------------------------- --------------------------
|
|
3207
|
+
* ```
|
|
3208
|
+
* ```typescript
|
|
3209
|
+
* const icons = await aui.get().icon().withText('user').exec();
|
|
3210
|
+
* console.log(icons);
|
|
3211
|
+
* ```
|
|
3212
|
+
* Using only the filter withText, the get command will return both icons because they share the same text
|
|
3213
|
+
* ```text
|
|
3214
|
+
* console output: [
|
|
3215
|
+
* DetectedElement {
|
|
3216
|
+
* name: 'ICON',
|
|
3217
|
+
* text: 'user',
|
|
3218
|
+
* colors: [ 'black', 'black', 'black' ],
|
|
3219
|
+
* bndbox: BoundingBox {
|
|
3220
|
+
* xmin: 1000,
|
|
3221
|
+
* ymin: 1010,
|
|
3222
|
+
* xmax: 1020,
|
|
3223
|
+
* ymax: 1030
|
|
3224
|
+
* }
|
|
3225
|
+
* },
|
|
3226
|
+
* DetectedElement {
|
|
3227
|
+
* name: 'ICON',
|
|
3228
|
+
* text: 'user',
|
|
3229
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
3230
|
+
* bndbox: BoundingBox {
|
|
3231
|
+
* xmin: 900,
|
|
3232
|
+
* ymin: 910,
|
|
3233
|
+
* xmax: 920,
|
|
3234
|
+
* ymax: 930
|
|
3235
|
+
* }
|
|
3236
|
+
* }
|
|
3237
|
+
* ]
|
|
3238
|
+
* ```
|
|
3239
|
+
* You can combine filters with **the `and()` relation** and specify exactly which icon you want
|
|
3240
|
+
* ```typescript
|
|
3241
|
+
* const icons = await aui.get().icon().withText('user').and().colored('red').exec()
|
|
3242
|
+
* console.log(icons)
|
|
3243
|
+
* ```
|
|
3244
|
+
* The get command returns only the red icon although both icons have the same text
|
|
3245
|
+
* ```text
|
|
3246
|
+
* console output: [
|
|
3247
|
+
* DetectedElement {
|
|
3248
|
+
* name: 'ICON',
|
|
3249
|
+
* text: 'user',
|
|
3250
|
+
* colors: [ 'red', 'red', 'red' ],
|
|
3251
|
+
* bndbox: BoundingBox {
|
|
3252
|
+
* xmin: 900,
|
|
3253
|
+
* ymin: 910,
|
|
3254
|
+
* xmax: 920,
|
|
3255
|
+
* ymax: 930
|
|
3256
|
+
* }
|
|
3257
|
+
* }
|
|
3258
|
+
* ]
|
|
3259
|
+
* ```
|
|
3260
|
+
*
|
|
3261
|
+
* @return {FluentFiltersGetter}
|
|
3262
|
+
*/
|
|
3263
|
+
and() {
|
|
3264
|
+
this._textStr = 'and';
|
|
3265
|
+
return new FluentFiltersGetter(this);
|
|
3266
|
+
}
|
|
2925
3267
|
/**
|
|
2926
3268
|
* Filters for an element inside another element.
|
|
2927
3269
|
*
|
|
@@ -3102,7 +3444,32 @@ export class FluentFiltersOrRelationsGetter extends FluentFiltersGetter {
|
|
|
3102
3444
|
// Commands
|
|
3103
3445
|
export class Getter extends FluentCommand {
|
|
3104
3446
|
/**
|
|
3105
|
-
* Returns
|
|
3447
|
+
* Returns an array with all filtered elements.
|
|
3448
|
+
* A detected element has the following properties:
|
|
3449
|
+
* - `name` of the element
|
|
3450
|
+
* - `text` content of element
|
|
3451
|
+
* - `colors` of element
|
|
3452
|
+
* - `bndbox`: location of element described with coordinates of a bounding box
|
|
3453
|
+
* **Examples:**
|
|
3454
|
+
* ```typescript
|
|
3455
|
+
* const text = await aui.get().text().withText('Sign').exec();
|
|
3456
|
+
* console.log(text);
|
|
3457
|
+
* ```
|
|
3458
|
+
* ```text
|
|
3459
|
+
* console output: [
|
|
3460
|
+
* DetectedElement {
|
|
3461
|
+
* name: 'TEXT',
|
|
3462
|
+
* text: 'Sign In',
|
|
3463
|
+
* colors: [ 'black', 'gray', 'gray' ],
|
|
3464
|
+
* bndbox: BoundingBox {
|
|
3465
|
+
* xmin: 1128.2720982142857,
|
|
3466
|
+
* ymin: 160.21332310267857,
|
|
3467
|
+
* xmax: 1178.8204241071428,
|
|
3468
|
+
* ymax: 180.83512834821428
|
|
3469
|
+
* }
|
|
3470
|
+
* }
|
|
3471
|
+
* ]
|
|
3472
|
+
* ```
|
|
3106
3473
|
*
|
|
3107
3474
|
* @return {FluentFiltersGetter}
|
|
3108
3475
|
*/
|
|
@@ -3111,7 +3478,43 @@ export class Getter extends FluentCommand {
|
|
|
3111
3478
|
return new FluentFiltersGetter(this);
|
|
3112
3479
|
}
|
|
3113
3480
|
/**
|
|
3114
|
-
* Returns all detected elements
|
|
3481
|
+
* Returns an array with all detected elements.
|
|
3482
|
+
* A detected element has the following properties:
|
|
3483
|
+
* - `name` of the element
|
|
3484
|
+
* - `text` content of element
|
|
3485
|
+
* - `colors` of element
|
|
3486
|
+
* - `bndbox`: location of element described with coordinates of a bounding box
|
|
3487
|
+
* **Examples:**
|
|
3488
|
+
* ```typescript
|
|
3489
|
+
* const detectedElements = await aui.getAll().exec();
|
|
3490
|
+
* console.log(detectedElements);
|
|
3491
|
+
* ```
|
|
3492
|
+
* ```text
|
|
3493
|
+
* console output: [
|
|
3494
|
+
* DetectedElement {
|
|
3495
|
+
* name: 'TEXT',
|
|
3496
|
+
* text: 'Sign In',
|
|
3497
|
+
* colors: [ 'black', 'gray', 'gray' ],
|
|
3498
|
+
* bndbox: BoundingBox {
|
|
3499
|
+
* xmin: 1128.2720982142857,
|
|
3500
|
+
* ymin: 160.21332310267857,
|
|
3501
|
+
* xmax: 1178.8204241071428,
|
|
3502
|
+
* ymax: 180.83512834821428
|
|
3503
|
+
* },
|
|
3504
|
+
* DetectedElement {
|
|
3505
|
+
* name: 'ICON',
|
|
3506
|
+
* text: 'search',
|
|
3507
|
+
* colors: [ 'black', 'red', 'gray' ],
|
|
3508
|
+
* bndbox: BoundingBox {
|
|
3509
|
+
* xmin: 250.8204241071428,
|
|
3510
|
+
* ymin: 300.21332310267857,
|
|
3511
|
+
* xmax: 450.6304241071428,
|
|
3512
|
+
* ymax: 950.47812834821428
|
|
3513
|
+
* },
|
|
3514
|
+
* ... 381 more items
|
|
3515
|
+
* }
|
|
3516
|
+
* ]
|
|
3517
|
+
* ```
|
|
3115
3518
|
*
|
|
3116
3519
|
* @return {ExecGetter}
|
|
3117
3520
|
*/
|
|
@@ -6,10 +6,11 @@ import { DetectedElement } from '../core/model/annotation-result/detected-elemen
|
|
|
6
6
|
export declare class InferenceClient {
|
|
7
7
|
baseUrl: string;
|
|
8
8
|
httpClient: HttpClientGot;
|
|
9
|
+
resize?: number | undefined;
|
|
9
10
|
readonly workspaceId?: string | undefined;
|
|
10
11
|
apiVersion: string;
|
|
11
12
|
url: string;
|
|
12
|
-
constructor(baseUrl: string, httpClient: HttpClientGot, workspaceId?: string | undefined, apiVersion?: string);
|
|
13
|
+
constructor(baseUrl: string, httpClient: HttpClientGot, resize?: number | undefined, workspaceId?: string | undefined, apiVersion?: string);
|
|
13
14
|
isImageRequired(instruction: string): Promise<boolean>;
|
|
14
15
|
private resizeIfNeeded;
|
|
15
16
|
inference(customElements?: CustomElement[], image?: string, instruction?: string): Promise<ControlCommand | Annotation>;
|
|
@@ -12,14 +12,20 @@ import { ControlCommand, InferenceResponse } from '../core/ui-control-commands';
|
|
|
12
12
|
import { Annotation } from '../core/annotation/annotation';
|
|
13
13
|
import { resizeBase64ImageWithSameRatio } from '../utils/transformations';
|
|
14
14
|
import { InferenceResponseError } from './inference-response-error';
|
|
15
|
+
import { ConfigurationError } from './config-error';
|
|
15
16
|
export class InferenceClient {
|
|
16
|
-
constructor(baseUrl, httpClient, workspaceId, apiVersion = 'v3') {
|
|
17
|
+
constructor(baseUrl, httpClient, resize, workspaceId, apiVersion = 'v3') {
|
|
17
18
|
this.baseUrl = baseUrl;
|
|
18
19
|
this.httpClient = httpClient;
|
|
20
|
+
this.resize = resize;
|
|
19
21
|
this.workspaceId = workspaceId;
|
|
20
22
|
this.apiVersion = apiVersion;
|
|
21
23
|
const versionedBaseUrl = urljoin(this.baseUrl, 'api', this.apiVersion);
|
|
22
24
|
this.url = workspaceId ? urljoin(versionedBaseUrl, 'workspaces', workspaceId) : versionedBaseUrl;
|
|
25
|
+
if (this.resize !== undefined && this.resize <= 0) {
|
|
26
|
+
throw new ConfigurationError(`Resize must be a positive number. The current resize value "${this.resize}" is not valid.`);
|
|
27
|
+
}
|
|
28
|
+
this.resize = this.resize ? Math.ceil(this.resize) : this.resize;
|
|
23
29
|
}
|
|
24
30
|
isImageRequired(instruction) {
|
|
25
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -34,10 +40,10 @@ export class InferenceClient {
|
|
|
34
40
|
// eslint-disable-next-line class-methods-use-this
|
|
35
41
|
resizeIfNeeded(customElements, image) {
|
|
36
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
if (!(image) || customElements.length > 0) {
|
|
43
|
+
if (!(image) || customElements.length > 0 || this.resize === undefined) {
|
|
38
44
|
return { base64Image: image, resizeRatio: 1 };
|
|
39
45
|
}
|
|
40
|
-
return resizeBase64ImageWithSameRatio(image);
|
|
46
|
+
return resizeBase64ImageWithSameRatio(image, this.resize);
|
|
41
47
|
});
|
|
42
48
|
}
|
|
43
49
|
inference(customElements = [], image, instruction) {
|
|
@@ -20,6 +20,7 @@ import { AnnotationLevel } from './annotation-level';
|
|
|
20
20
|
import { UiControlClientError } from './ui-control-client-error';
|
|
21
21
|
import { envCredentials } from './read-environment-credentials';
|
|
22
22
|
import { Analytics } from '../utils/analytics';
|
|
23
|
+
import { buildProxyAgentArgsFromEnvironment } from '../utils/proxy/proxy-builder';
|
|
23
24
|
const getClientArgsWithDefaults = (clientArgs = {}) => (Object.assign({ uiControllerUrl: 'http://127.0.0.1:6769', inferenceServerUrl: 'https://inference.askui.com', annotationLevel: AnnotationLevel.DISABLED }, clientArgs));
|
|
24
25
|
export class UiControlClient extends ApiCommands {
|
|
25
26
|
constructor(httpClient, clientArgs, workspaceId) {
|
|
@@ -36,7 +37,8 @@ export class UiControlClient extends ApiCommands {
|
|
|
36
37
|
const analyticsCookies = yield analytics.getAnalyticsCookies();
|
|
37
38
|
const cas = getClientArgsWithDefaults(clientArgs);
|
|
38
39
|
const credentialArgs = cas.credentials || envCredentials();
|
|
39
|
-
const
|
|
40
|
+
const proxyAgentArgs = cas.proxyAgents || (yield buildProxyAgentArgsFromEnvironment());
|
|
41
|
+
const httpClient = new HttpClientGot(credentialArgs === null || credentialArgs === void 0 ? void 0 : credentialArgs.token, analyticsHeaders, analyticsCookies, proxyAgentArgs);
|
|
40
42
|
return new UiControlClient(httpClient, cas, credentialArgs === null || credentialArgs === void 0 ? void 0 : credentialArgs.workspaceId);
|
|
41
43
|
});
|
|
42
44
|
}
|
|
@@ -47,7 +49,7 @@ export class UiControlClient extends ApiCommands {
|
|
|
47
49
|
return this._uiControllerClient;
|
|
48
50
|
}
|
|
49
51
|
get inferenceClient() {
|
|
50
|
-
return new InferenceClient(this.clientArgs.inferenceServerUrl, this.httpClient, this.workspaceId);
|
|
52
|
+
return new InferenceClient(this.clientArgs.inferenceServerUrl, this.httpClient, this.clientArgs.resize, this.workspaceId);
|
|
51
53
|
}
|
|
52
54
|
get executionRuntime() {
|
|
53
55
|
return new ExecutionRuntime(this.uiControllerClient, this.inferenceClient);
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { AnnotationLevel } from './annotation-level';
|
|
2
2
|
import { CredentialArgs } from './credentials-args';
|
|
3
|
+
import { ProxyAgentArgs } from '../shared/proxy-agent-args';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration options for the askui UI Control Client
|
|
5
6
|
*
|
|
6
7
|
* @param {string} uiControllerUrl - Default: http://127.0.0.1:6769
|
|
7
8
|
* The adress of the askui UI Controller server.
|
|
9
|
+
* @param {(number | undefined)} resize - Default: undefined
|
|
10
|
+
* The resizing will be skipped if it's undefined.
|
|
11
|
+
* The side length of the target image to resize to in px.
|
|
12
|
+
* Your screenshot image will be resized with the original aspect ratio,
|
|
13
|
+
* and the lengths image side will be equal to this number.
|
|
14
|
+
* This can be used to reduce the inference time by reducing
|
|
15
|
+
* the request size in case of a bad internet connection.
|
|
16
|
+
* But it can cause a decrease in the prediction quality.
|
|
8
17
|
* @param {string} inferenceClientUrl - Default: https://inference.askui.com`
|
|
9
18
|
* Address of the askui Inference server.
|
|
10
19
|
* @param {AnnotationLevel} annotationLevel - Default: AnnotationLevel.DISABLED
|
|
@@ -13,12 +22,16 @@ import { CredentialArgs } from './credentials-args';
|
|
|
13
22
|
* You have three options: `DISABLED`, `ON_FAILURE`, `ALL`.
|
|
14
23
|
* @param {CredentialArgs} credentials - We need to provide credentials for
|
|
15
24
|
* the authentication of the askui Inference Server.
|
|
25
|
+
* You have three options: `DISABLED`, `ON_FAILURE`, `ALL`.
|
|
26
|
+
* @param {ProxyAgentArgs} proxyAgents - To configure the proxy agents for http(s) requests.
|
|
16
27
|
*/
|
|
17
28
|
export interface ClientArgs {
|
|
18
29
|
readonly uiControllerUrl?: string;
|
|
19
30
|
readonly inferenceServerUrl?: string;
|
|
20
31
|
readonly annotationLevel?: AnnotationLevel;
|
|
21
32
|
readonly credentials?: CredentialArgs;
|
|
33
|
+
readonly proxyAgents?: ProxyAgentArgs;
|
|
34
|
+
readonly resize?: number;
|
|
22
35
|
}
|
|
23
36
|
export interface ClientArgsWithDefaults extends ClientArgs {
|
|
24
37
|
readonly uiControllerUrl: string;
|
|
@@ -1,15 +1,46 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { Command } from 'commander';
|
|
2
11
|
import path from 'path';
|
|
3
12
|
import fs from 'fs-extra';
|
|
4
13
|
import { getPathToNodeModulesRoot } from '../utils/path';
|
|
14
|
+
import { logger } from './logger';
|
|
5
15
|
const createProgram = () => {
|
|
6
16
|
const program = new Command('askui');
|
|
7
17
|
program.usage('<command> [options]');
|
|
8
18
|
return program;
|
|
9
19
|
};
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
function replaceStringInFile(filePath, replace, replacement) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
try {
|
|
23
|
+
const data = yield fs.readFile(filePath, 'utf8');
|
|
24
|
+
const result = data.replace(replace, replacement);
|
|
25
|
+
yield fs.writeFile(filePath, result, 'utf8');
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
logger.error(`Could not replace '${replace}' with '${replacement}' in file '${path}'`);
|
|
29
|
+
logger.error(error.message);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function copyExampleProject(options) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
const exampleProjectPath = path.join('example_projects_templates', 'typescript_jest');
|
|
36
|
+
fs.copySync(path.join(getPathToNodeModulesRoot(), exampleProjectPath), '.');
|
|
37
|
+
if (options['workspaceId']) {
|
|
38
|
+
yield replaceStringInFile('./test/helper/jest.setup.ts', '<your workspace id>', options['workspaceId']);
|
|
39
|
+
}
|
|
40
|
+
if (options['accessToken']) {
|
|
41
|
+
yield replaceStringInFile('./test/helper/jest.setup.ts', '<your access token>', options['accessToken']);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
13
44
|
}
|
|
14
45
|
export function init(argv) {
|
|
15
46
|
const args = argv || process.argv;
|
|
@@ -17,6 +48,11 @@ export function init(argv) {
|
|
|
17
48
|
program
|
|
18
49
|
.command('init')
|
|
19
50
|
.description('creates a typescript example project')
|
|
20
|
-
.
|
|
51
|
+
.option('-w, --workspace-id <value>', 'a workspace id')
|
|
52
|
+
.option('-a, --access-token <value>', 'an access token for the workspace with the id')
|
|
53
|
+
.usage('[-w workspace_id] [-a access_token]')
|
|
54
|
+
.action((opts) => __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
yield copyExampleProject(opts);
|
|
56
|
+
}));
|
|
21
57
|
return program.parse(args);
|
|
22
58
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import http from 'http';
|
|
3
|
+
import https from 'https';
|
|
1
4
|
declare enum SupportedPlatform {
|
|
2
5
|
LINUX = "linux",
|
|
3
6
|
DARWIN = "darwin",
|
|
@@ -5,5 +8,8 @@ declare enum SupportedPlatform {
|
|
|
5
8
|
}
|
|
6
9
|
export declare function platform(): SupportedPlatform;
|
|
7
10
|
export declare function getBinaryPath(version: string): string;
|
|
8
|
-
export declare function downloadServerBinaries(binaryVersion: string
|
|
11
|
+
export declare function downloadServerBinaries(binaryVersion: string, proxyAgent?: {
|
|
12
|
+
http: http.Agent;
|
|
13
|
+
https: https.Agent;
|
|
14
|
+
}): Promise<void>;
|
|
9
15
|
export {};
|
|
@@ -36,7 +36,7 @@ function getBinaryDownloadUrl(binaryVersion) {
|
|
|
36
36
|
const arch = os.arch();
|
|
37
37
|
return `${baseUrl}/${platform()}/${arch}/${binarySubPathsByPlatform[platform()][1]}`;
|
|
38
38
|
}
|
|
39
|
-
export function downloadServerBinaries(binaryVersion) {
|
|
39
|
+
export function downloadServerBinaries(binaryVersion, proxyAgent) {
|
|
40
40
|
return new Promise((resolve, reject) => {
|
|
41
41
|
const url = getBinaryDownloadUrl(binaryVersion);
|
|
42
42
|
const binaryOutputPath = getBinaryPath(binaryVersion);
|
|
@@ -45,7 +45,7 @@ export function downloadServerBinaries(binaryVersion) {
|
|
|
45
45
|
if (!(fs.existsSync(binaryFolder))) {
|
|
46
46
|
fs.mkdirSync(binaryFolder, { recursive: true });
|
|
47
47
|
}
|
|
48
|
-
const downloadStream = got.stream(url);
|
|
48
|
+
const downloadStream = got.stream(url, proxyAgent ? { agent: proxyAgent } : {});
|
|
49
49
|
const fileWriterStream = fs.createWriteStream(binaryOutputPath);
|
|
50
50
|
downloadStream.on('error', () => {
|
|
51
51
|
reject();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProxyAgentArgs } from '../shared/proxy-agent-args';
|
|
1
2
|
import { LogLevels } from '../shared/log-levels';
|
|
2
3
|
/**
|
|
3
4
|
* Configuration options for the askui UI Controller
|
|
@@ -5,6 +6,7 @@ import { LogLevels } from '../shared/log-levels';
|
|
|
5
6
|
* @param {number} display - Default: `0`
|
|
6
7
|
* You can choose on which display you want to excecute all tests.
|
|
7
8
|
* 0 is your main monitor.
|
|
9
|
+
*
|
|
8
10
|
* If you want to use your second monitor you can change
|
|
9
11
|
* the value to `1` (`2` for your third monitor etc.).
|
|
10
12
|
* @param {string} binaryVersion - Default: `'latest'`
|
|
@@ -26,6 +28,7 @@ import { LogLevels } from '../shared/log-levels';
|
|
|
26
28
|
* @param {string} logFilePath - Default: `'<temp-dir>/askui/askui-server.log'`
|
|
27
29
|
* It is possible to specify a path for your log files.
|
|
28
30
|
* Per default we create the askui-server.log file and askui folder in your temp folder.
|
|
31
|
+
* @param {ProxyAgentArgs} proxyAgents - To configure the proxy agents for our http(s) requests.
|
|
29
32
|
*/
|
|
30
33
|
export interface UiControllerArgs {
|
|
31
34
|
readonly display?: number;
|
|
@@ -37,6 +40,7 @@ export interface UiControllerArgs {
|
|
|
37
40
|
readonly overWriteBinary?: boolean;
|
|
38
41
|
readonly logLevel?: LogLevels;
|
|
39
42
|
readonly logFilePath?: string;
|
|
43
|
+
readonly proxyAgents?: ProxyAgentArgs;
|
|
40
44
|
}
|
|
41
45
|
export interface UiControllerArgsWithDefaults extends UiControllerArgs {
|
|
42
46
|
readonly display: number;
|