@aspiresys/visor 1.1.5 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ const config_1 = require("./config");
10
10
  const app_1 = require("./app");
11
11
  const nut_js_1 = require("@nut-tree-fork/nut-js");
12
12
  const path_1 = require("./path");
13
+ const display_1 = require("./display");
14
+ const logger_1 = require("./logger");
13
15
  class Visor {
14
16
  constructor() {
15
17
  this.mouse = nut_js_1.mouse;
@@ -18,72 +20,72 @@ class Visor {
18
20
  this.Button = nut_js_1.Button;
19
21
  }
20
22
  /**
21
- * Finds an image on screen using OpenCV
22
- * and performs a left mouse click
23
- * on the matched region.
24
- *
25
- * @param image Optional image filename or path.
26
- *
27
- * @param confidence Match confidence threshold.
28
- *
29
- * Accepted range:
30
- * 0.0 to 1.0
31
- *
32
- * Default:
33
- * 0.8
34
- *
35
- * Recommended values:
36
- * - 0.7 for dynamic UI
37
- * - 0.8 for standard usage
38
- * - 0.9+ for strict matching
39
- *
40
- * Lower confidence increases
41
- * flexibility but may increase
42
- * false positives.
43
- *
44
- * @example
45
- * await visor.click("save.png");
46
- *
47
- * @example
48
- * await visor.click("./images/save.png", 0.9);
49
- */
23
+ * Finds an image on screen using OpenCV
24
+ * and performs a left mouse click
25
+ * on the matched region.
26
+ *
27
+ * @param image Optional image filename or path.
28
+ *
29
+ * @param confidence Match confidence threshold.
30
+ *
31
+ * Accepted range:
32
+ * 0.0 to 1.0
33
+ *
34
+ * Default:
35
+ * 0.8
36
+ *
37
+ * Recommended values:
38
+ * - 0.7 for dynamic UI
39
+ * - 0.8 for standard usage
40
+ * - 0.9+ for strict matching
41
+ *
42
+ * Lower confidence increases
43
+ * flexibility but may increase
44
+ * false positives.
45
+ *
46
+ * @example
47
+ * await visor.click("save.png");
48
+ *
49
+ * @example
50
+ * await visor.click("./images/save.png", 0.9);
51
+ */
50
52
  async click(image, confidence = 0.8) {
51
53
  if (!image) {
52
54
  await this.mouse.click(this.Button.LEFT);
53
- console.log("[MOUSE] Left click completed");
55
+ (0, logger_1.log)("[MOUSE] Left click completed");
54
56
  return;
55
57
  }
56
58
  const region = await this.find(image, confidence);
57
59
  if (!region) {
58
60
  throw new Error(`Image not found: ${image}`);
59
61
  }
60
- console.log("[CV] Match found:", region);
62
+ (0, logger_1.log)("[CV] Match found:", region);
61
63
  await (0, mouse_1.clickRegion)(region);
62
64
  }
63
65
  /**
64
- * Performs a right mouse click.
65
- *
66
- * If an image is provided, the framework
67
- * first finds the image on screen and
68
- * moves the mouse to the matched region
69
- * before performing the click.
70
- *
71
- * @param image Image filename or path.
72
- * @param confidence Match confidence threshold.
73
- *
74
- * Accepted range:
75
- * 0.0 to 1.0
76
- *
77
- * Default:
78
- * 0.8
79
- * @throws Error if image is not found.
80
- *
81
- * @example
82
- * await visor.rightClick("file.png");
83
- *
84
- * @example
85
- * await visor.rightClick();
86
- */
66
+ * Performs a right mouse click.
67
+ *
68
+ * If an image is provided, the framework
69
+ * first finds the image on screen and
70
+ * moves the mouse to the matched region
71
+ * before performing the click.
72
+ *
73
+ * @param image Image filename or path.
74
+ * @param confidence Match confidence threshold.
75
+ *
76
+ * Accepted range:
77
+ * 0.0 to 1.0
78
+ *
79
+ * Default:
80
+ * 0.8
81
+ * @throws Error if image is not found.
82
+ *
83
+ * @example
84
+ * await visor.rightClick("file.png");
85
+ *
86
+ * @example
87
+ * await visor.rightClick();
88
+ */
87
89
  async rightClick(image, confidence = 0.8) {
88
90
  if (image) {
89
91
  const region = await this.find(image, confidence);
@@ -93,33 +95,33 @@ class Visor {
93
95
  await (0, mouse_1.moveToRegion)(region);
94
96
  }
95
97
  await this.mouse.click(this.Button.RIGHT);
96
- console.log("[MOUSE] Right click completed");
98
+ (0, logger_1.log)("[MOUSE] Right click completed");
97
99
  }
98
100
  /**
99
- * Performs a double left mouse click.
100
- *
101
- * If an image is provided, the framework
102
- * first finds the image on screen and
103
- * moves the mouse to the matched region
104
- * before performing the click.
105
- *
106
- * @param image Image filename or path.
107
- * @param confidence Match confidence threshold.
108
- *
109
- * Accepted range:
110
- * 0.0 to 1.0
111
- *
112
- * Default:
113
- * 0.8
114
- *
115
- * @throws Error if image is not found.
116
- *
117
- * @example
118
- * await visor.doubleClick("folder.png");
119
- *
120
- * @example
121
- * await visor.doubleClick();
122
- */
101
+ * Performs a double left mouse click.
102
+ *
103
+ * If an image is provided, the framework
104
+ * first finds the image on screen and
105
+ * moves the mouse to the matched region
106
+ * before performing the click.
107
+ *
108
+ * @param image Image filename or path.
109
+ * @param confidence Match confidence threshold.
110
+ *
111
+ * Accepted range:
112
+ * 0.0 to 1.0
113
+ *
114
+ * Default:
115
+ * 0.8
116
+ *
117
+ * @throws Error if image is not found.
118
+ *
119
+ * @example
120
+ * await visor.doubleClick("folder.png");
121
+ *
122
+ * @example
123
+ * await visor.doubleClick();
124
+ */
123
125
  async doubleClick(image, confidence = 0.8) {
124
126
  if (image) {
125
127
  const region = await this.find(image, confidence);
@@ -129,37 +131,37 @@ class Visor {
129
131
  await (0, mouse_1.moveToRegion)(region);
130
132
  }
131
133
  await this.mouse.doubleClick(this.Button.LEFT);
132
- console.log("[MOUSE] Double click completed");
134
+ (0, logger_1.log)("[MOUSE] Double click completed");
133
135
  }
134
136
  /**
135
- * Finds the best matching image on screen
136
- * using OpenCV template matching.
137
- *
138
- * @param image Image filename or path.
139
- *
140
- * @param confidence Match confidence threshold.
141
- *
142
- * Accepted range:
143
- * 0.0 to 1.0
144
- *
145
- * Default:
146
- * 0.8
147
- *
148
- * Recommended values:
149
- * - 0.7 for dynamic UI
150
- * - 0.8 for standard usage
151
- * - 0.9+ for strict matching
152
- *
153
- * Higher confidence improves
154
- * matching accuracy but may fail
155
- * on scaled or slightly modified UI.
156
- *
157
- * @returns Best matched region or null.
158
- *
159
- * @example
160
- * const region =
161
- * await visor.find("save.png");
162
- */
137
+ * Finds the best matching image on screen
138
+ * using OpenCV template matching.
139
+ *
140
+ * @param image Image filename or path.
141
+ *
142
+ * @param confidence Match confidence threshold.
143
+ *
144
+ * Accepted range:
145
+ * 0.0 to 1.0
146
+ *
147
+ * Default:
148
+ * 0.8
149
+ *
150
+ * Recommended values:
151
+ * - 0.7 for dynamic UI
152
+ * - 0.8 for standard usage
153
+ * - 0.9+ for strict matching
154
+ *
155
+ * Higher confidence improves
156
+ * matching accuracy but may fail
157
+ * on scaled or slightly modified UI.
158
+ *
159
+ * @returns Best matched region or null.
160
+ *
161
+ * @example
162
+ * const region =
163
+ * await visor.find("save.png");
164
+ */
163
165
  async find(image, confidence = 0.8) {
164
166
  const screen = await (0, screen_1.captureScreen)();
165
167
  const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
@@ -172,49 +174,49 @@ class Visor {
172
174
  }
173
175
  }
174
176
  /**
175
- * Checks whether an image exists
176
- * on the current screen.
177
- *
178
- * @param image Image filename or path.
179
- * @param confidence Match confidence threshold.
180
- *
181
- * Accepted range:
182
- * 0.0 to 1.0
183
- *
184
- * Default:
185
- * 0.8
186
- *
187
- * @returns True if image exists.
188
- *
189
- * @example
190
- * const exists =
191
- * await visor.exists("login.png");
192
- */
177
+ * Checks whether an image exists
178
+ * on the current screen.
179
+ *
180
+ * @param image Image filename or path.
181
+ * @param confidence Match confidence threshold.
182
+ *
183
+ * Accepted range:
184
+ * 0.0 to 1.0
185
+ *
186
+ * Default:
187
+ * 0.8
188
+ *
189
+ * @returns True if image exists.
190
+ *
191
+ * @example
192
+ * const exists =
193
+ * await visor.exists("login.png");
194
+ */
193
195
  async exists(image, confidence = 0.8) {
194
196
  return (await this.find(image, confidence)) !== null;
195
197
  }
196
198
  /**
197
- * Finds all matching occurrences of an image
198
- * on the current screen using OpenCV.
199
- *
200
- * @param image Image filename or path.
201
- * @param confidence Match confidence threshold.
202
- *
203
- * Accepted range:
204
- * 0.0 to 1.0
205
- *
206
- * Default:
207
- * 0.8
208
- *
209
- * Lower confidence may return
210
- * more false-positive matches.
211
- *
212
- * @returns Array of matched regions.
213
- *
214
- * @example
215
- * const matches =
216
- * await visor.findAll("icon.png");
217
- */
199
+ * Finds all matching occurrences of an image
200
+ * on the current screen using OpenCV.
201
+ *
202
+ * @param image Image filename or path.
203
+ * @param confidence Match confidence threshold.
204
+ *
205
+ * Accepted range:
206
+ * 0.0 to 1.0
207
+ *
208
+ * Default:
209
+ * 0.8
210
+ *
211
+ * Lower confidence may return
212
+ * more false-positive matches.
213
+ *
214
+ * @returns Array of matched regions.
215
+ *
216
+ * @example
217
+ * const matches =
218
+ * await visor.findAll("icon.png");
219
+ */
218
220
  async findAll(image, confidence = 0.8) {
219
221
  const screen = await (0, screen_1.captureScreen)();
220
222
  const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
@@ -227,32 +229,32 @@ class Visor {
227
229
  }
228
230
  }
229
231
  /**
230
- * Finds all image matches and prints
231
- * a formatted match preview including
232
- * coordinates and confidence values.
233
- *
234
- * Useful for debugging and visual
235
- * automation tuning.
236
- *
237
- * @param image Image filename or path.
238
- * @param confidence Match confidence threshold.
239
- *
240
- * Accepted range:
241
- * 0.0 to 1.0
242
- *
243
- * Default:
244
- * 0.8
245
- *
246
- * @returns Array of matched regions.
247
- *
248
- * @example
249
- * await visor.previewMatches("button.png");
250
- */
232
+ * Finds all image matches and prints
233
+ * a formatted match preview including
234
+ * coordinates and confidence values.
235
+ *
236
+ * Useful for debugging and visual
237
+ * automation tuning.
238
+ *
239
+ * @param image Image filename or path.
240
+ * @param confidence Match confidence threshold.
241
+ *
242
+ * Accepted range:
243
+ * 0.0 to 1.0
244
+ *
245
+ * Default:
246
+ * 0.8
247
+ *
248
+ * @returns Array of matched regions.
249
+ *
250
+ * @example
251
+ * await visor.previewMatches("button.png");
252
+ */
251
253
  async previewMatches(image, confidence = 0.8) {
252
254
  const matches = await this.findAll(image, confidence);
253
- console.log("\n=== MATCH PREVIEW ===\n");
255
+ (0, logger_1.log)("\n=== MATCH PREVIEW ===\n");
254
256
  matches.forEach((m, i) => {
255
- console.log(`#${i + 1}
257
+ (0, logger_1.log)(`#${i + 1}
256
258
  X:${m.x}
257
259
  Y:${m.y}
258
260
  W:${m.width}
@@ -263,40 +265,40 @@ CONF:${m.confidence.toFixed(3)}
263
265
  return matches;
264
266
  }
265
267
  /**
266
- * Waits until an image appears
267
- * on the screen.
268
- *
269
- * @param image Image filename or path.
270
- *
271
- * @param confidence Match confidence threshold.
272
- *
273
- * Accepted range:
274
- * 0.0 to 1.0
275
- *
276
- * Default:
277
- * 0.8
278
- *
279
- * Recommended values:
280
- * - 0.7 for dynamic UI
281
- * - 0.8 for standard usage
282
- * - 0.9+ for strict matching
283
- *
284
- * @param timeout Timeout duration
285
- * in milliseconds.
286
- *
287
- * Default:
288
- * 5000ms
289
- *
290
- * Recommended range:
291
- * 1000ms to 30000ms
292
- *
293
- * @throws Error if timeout occurs.
294
- *
295
- * @example
296
- * await visor.wait("loading-done.png");
297
- */
268
+ * Waits until an image appears
269
+ * on the screen.
270
+ *
271
+ * @param image Image filename or path.
272
+ *
273
+ * @param confidence Match confidence threshold.
274
+ *
275
+ * Accepted range:
276
+ * 0.0 to 1.0
277
+ *
278
+ * Default:
279
+ * 0.8
280
+ *
281
+ * Recommended values:
282
+ * - 0.7 for dynamic UI
283
+ * - 0.8 for standard usage
284
+ * - 0.9+ for strict matching
285
+ *
286
+ * @param timeout Timeout duration
287
+ * in milliseconds.
288
+ *
289
+ * Default:
290
+ * 5000ms
291
+ *
292
+ * Recommended range:
293
+ * 1000ms to 30000ms
294
+ *
295
+ * @throws Error if timeout occurs.
296
+ *
297
+ * @example
298
+ * await visor.wait("loading-done.png");
299
+ */
298
300
  async wait(image, { confidence = 0.8, timeout = 5000 } = {}) {
299
- const interval = 1000;
301
+ const interval = 300;
300
302
  const attempts = Math.ceil(timeout / interval);
301
303
  for (let i = 0; i < attempts; i++) {
302
304
  if (await this.exists(image, confidence)) {
@@ -307,30 +309,30 @@ CONF:${m.confidence.toFixed(3)}
307
309
  throw new Error(`Timeout waiting for image: ${image}`);
308
310
  }
309
311
  /**
310
- * Waits until an image disappears
311
- * from the screen.
312
- *
313
- * @param image Image filename or path.
314
- * @param confidence Match confidence threshold.
315
- *
316
- * Accepted range:
317
- * 0.0 to 1.0
318
- *
319
- * Default:
320
- * 0.8
321
- * @param timeout Timeout duration
322
- * in milliseconds.
323
- *
324
- * Default:
325
- * 5000ms
326
- *
327
- * Recommended range:
328
- * 1000ms to 30000ms
329
- * @throws Error if timeout occurs.
330
- *
331
- * @example
332
- * await visor.waitToVanish("spinner.png");
333
- */
312
+ * Waits until an image disappears
313
+ * from the screen.
314
+ *
315
+ * @param image Image filename or path.
316
+ * @param confidence Match confidence threshold.
317
+ *
318
+ * Accepted range:
319
+ * 0.0 to 1.0
320
+ *
321
+ * Default:
322
+ * 0.8
323
+ * @param timeout Timeout duration
324
+ * in milliseconds.
325
+ *
326
+ * Default:
327
+ * 5000ms
328
+ *
329
+ * Recommended range:
330
+ * 1000ms to 30000ms
331
+ * @throws Error if timeout occurs.
332
+ *
333
+ * @example
334
+ * await visor.waitToVanish("spinner.png");
335
+ */
334
336
  async waitToVanish(image, { confidence = 0.8, timeout = 5000 } = {}) {
335
337
  const start = Date.now();
336
338
  while (Date.now() - start < timeout) {
@@ -342,30 +344,30 @@ CONF:${m.confidence.toFixed(3)}
342
344
  throw new Error(`Timeout waiting for image to vanish: ${image}`);
343
345
  }
344
346
  /**
345
- * Waits until specific text appears
346
- * on screen using OCR.
347
- *
348
- * Performance Note:
349
- * OCR operations are computationally
350
- * expensive and may take 1–5 seconds
351
- * depending on screen complexity.
352
- *
353
- * @param text Text to search for.
354
- *
355
- * @param timeout Timeout duration
356
- * in milliseconds.
357
- *
358
- * Default:
359
- * 5000ms
360
- *
361
- * Recommended range:
362
- * 1000ms to 30000ms
363
- *
364
- * @throws Error if timeout occurs.
365
- *
366
- * @example
367
- * await visor.waitText("Success");
368
- */
347
+ * Waits until specific text appears
348
+ * on screen using OCR.
349
+ *
350
+ * Performance Note:
351
+ * OCR operations are computationally
352
+ * expensive and may take 1–5 seconds
353
+ * depending on screen complexity.
354
+ *
355
+ * @param text Text to search for.
356
+ *
357
+ * @param timeout Timeout duration
358
+ * in milliseconds.
359
+ *
360
+ * Default:
361
+ * 5000ms
362
+ *
363
+ * Recommended range:
364
+ * 1000ms to 30000ms
365
+ *
366
+ * @throws Error if timeout occurs.
367
+ *
368
+ * @example
369
+ * await visor.waitText("Success");
370
+ */
369
371
  async waitText(text, timeout = 5000) {
370
372
  const start = Date.now();
371
373
  while (Date.now() - start < timeout) {
@@ -377,28 +379,28 @@ CONF:${m.confidence.toFixed(3)}
377
379
  throw new Error(`Timeout waiting for text: ${text}`);
378
380
  }
379
381
  /**
380
- * Waits until specific text disappears
381
- * from screen using OCR.
382
- * Performance Note:
383
- * OCR operations are computationally
384
- * expensive and may take 1–5 seconds
385
- * depending on screen complexity.
386
- *
387
- * @param text Text to search for.
388
- * @param timeout Timeout duration
389
- * in milliseconds.
390
- *
391
- * Default:
392
- * 5000ms
393
- *
394
- * Recommended range:
395
- * 1000ms to 30000ms
396
- *
397
- * @throws Error if timeout occurs.
398
- *
399
- * @example
400
- * await visor.waitTextToVanish("Loading");
401
- */
382
+ * Waits until specific text disappears
383
+ * from screen using OCR.
384
+ * Performance Note:
385
+ * OCR operations are computationally
386
+ * expensive and may take 1–5 seconds
387
+ * depending on screen complexity.
388
+ *
389
+ * @param text Text to search for.
390
+ * @param timeout Timeout duration
391
+ * in milliseconds.
392
+ *
393
+ * Default:
394
+ * 5000ms
395
+ *
396
+ * Recommended range:
397
+ * 1000ms to 30000ms
398
+ *
399
+ * @throws Error if timeout occurs.
400
+ *
401
+ * @example
402
+ * await visor.waitTextToVanish("Loading");
403
+ */
402
404
  async waitTextToVanish(text, timeout = 5000) {
403
405
  const start = Date.now();
404
406
  while (Date.now() - start < timeout) {
@@ -410,18 +412,18 @@ CONF:${m.confidence.toFixed(3)}
410
412
  throw new Error(`Timeout waiting for text to vanish: ${text}`);
411
413
  }
412
414
  /**
413
- * Finds text on screen using OCR
414
- * and performs a left mouse click
415
- * on the matched text region.
416
- *
417
- * @param text Text to search for.
418
- * @param index Index of the text to click.
419
- *
420
- * @throws Error if text is not found.
421
- *
422
- * @example
423
- * await visor.clickText("Login");
424
- */
415
+ * Finds text on screen using OCR
416
+ * and performs a left mouse click
417
+ * on the matched text region.
418
+ *
419
+ * @param text Text to search for.
420
+ * @param index Index of the text to click.
421
+ *
422
+ * @throws Error if text is not found.
423
+ *
424
+ * @example
425
+ * await visor.clickText("Login");
426
+ */
425
427
  async clickText(text, index = 0) {
426
428
  const region = await (0, text_1.findText)(text, index);
427
429
  if (!region) {
@@ -430,167 +432,167 @@ CONF:${m.confidence.toFixed(3)}
430
432
  await (0, mouse_1.clickRegion)(region);
431
433
  }
432
434
  /**
433
- * Finds text on screen or inside
434
- * a specific region using OCR.
435
- *
436
- * @param text Text to search for.
437
- * @param index Index of the text to search.
438
- * @param region Optional search region.
439
- *
440
- * @returns Matched text region or null.
441
- *
442
- * @example
443
- * const region =
444
- * await visor.findText("Submit");
445
- */
435
+ * Finds text on screen or inside
436
+ * a specific region using OCR.
437
+ *
438
+ * @param text Text to search for.
439
+ * @param index Index of the text to search.
440
+ * @param region Optional search region.
441
+ *
442
+ * @returns Matched text region or null.
443
+ *
444
+ * @example
445
+ * const region =
446
+ * await visor.findText("Submit");
447
+ */
446
448
  async findText(text, index = 0, region) {
447
449
  return await (0, text_1.findText)(text, index, region);
448
450
  }
449
451
  /**
450
- * Checks whether specific text exists
451
- * on screen using OCR.
452
- *
453
- * @param text Text to search for.
454
- * @param region Optional search region.
455
- *
456
- * @returns True if text exists.
457
- *
458
- * @example
459
- * const exists =
460
- * await visor.existsText("Teams");
461
- */
452
+ * Checks whether specific text exists
453
+ * on screen using OCR.
454
+ *
455
+ * @param text Text to search for.
456
+ * @param region Optional search region.
457
+ *
458
+ * @returns True if text exists.
459
+ *
460
+ * @example
461
+ * const exists =
462
+ * await visor.existsText("Teams");
463
+ */
462
464
  async existsText(text, region) {
463
465
  return await (0, text_1.existsText)(text, region);
464
466
  }
465
467
  /**
466
- * Performs OCR on a specific
467
- * screen region.
468
- *
469
- * @param region Screen region coordinates.
470
- *
471
- * @returns OCR result object.
472
- *
473
- * @example
474
- * const result =
475
- * await visor.readRegion({
476
- * x: 100,
477
- * y: 100,
478
- * width: 500,
479
- * height: 300
480
- * });
481
- */
468
+ * Performs OCR on a specific
469
+ * screen region.
470
+ *
471
+ * @param region Screen region coordinates.
472
+ *
473
+ * @returns OCR result object.
474
+ *
475
+ * @example
476
+ * const result =
477
+ * await visor.readRegion({
478
+ * x: 100,
479
+ * y: 100,
480
+ * width: 500,
481
+ * height: 300
482
+ * });
483
+ */
482
484
  async readRegion(region) {
483
485
  return await (0, ocr_1.extractTextFromRegion)(region);
484
486
  }
485
487
  /**
486
- * Performs OCR on the entire screen
487
- * using Tesseract OCR.
488
- *
489
- * Captures the current screen,
490
- * preprocesses the image, and
491
- * extracts readable text content.
492
- *
493
- * Performance Note:
494
- * OCR is computationally expensive
495
- * and may take 1–5 seconds depending
496
- * on:
497
- * - screen complexity
498
- * - text density
499
- * - display resolution
500
- * - system performance
501
- *
502
- * Returns:
503
- * - extracted text
504
- * - OCR metadata
505
- * - TSV layout information
506
- * - HOCR data
507
- *
508
- * @returns OCR result object.
509
- *
510
- * @example
511
- * const result =
512
- * await visor.readScreen();
513
- *
514
- * console.log(result.text);
515
- */
488
+ * Performs OCR on the entire screen
489
+ * using Tesseract OCR.
490
+ *
491
+ * Captures the current screen,
492
+ * preprocesses the image, and
493
+ * extracts readable text content.
494
+ *
495
+ * Performance Note:
496
+ * OCR is computationally expensive
497
+ * and may take 1–5 seconds depending
498
+ * on:
499
+ * - screen complexity
500
+ * - text density
501
+ * - display resolution
502
+ * - system performance
503
+ *
504
+ * Returns:
505
+ * - extracted text
506
+ * - OCR metadata
507
+ * - TSV layout information
508
+ * - HOCR data
509
+ *
510
+ * @returns OCR result object.
511
+ *
512
+ * @example
513
+ * const result =
514
+ * await visor.readScreen();
515
+ *
516
+ * log(result.text);
517
+ */
516
518
  async readScreen() {
517
519
  return await (0, ocr_1.extractTextFromRegion)();
518
520
  }
519
521
  /**
520
- * Captures a screenshot of the
521
- * current screen and saves it
522
- * to the specified path.
523
- *
524
- * Supported formats depend on
525
- * the output file extension.
526
- *
527
- * @param path Output image path.
528
- *
529
- * @example
530
- * await visor.captureScreenshot(
531
- * "./screenshots/home.png"
532
- * );
533
- */
522
+ * Captures a screenshot of the
523
+ * current screen and saves it
524
+ * to the specified path.
525
+ *
526
+ * Supported formats depend on
527
+ * the output file extension.
528
+ *
529
+ * @param path Output image path.
530
+ *
531
+ * @example
532
+ * await visor.captureScreenshot(
533
+ * "./screenshots/home.png"
534
+ * );
535
+ */
534
536
  async captureScreenshot(path) {
535
537
  path = config_1.visorConfig.outputPath + "/" + path;
536
- console.log(`[VISOR] Saving screenshot: ${path}`);
538
+ (0, logger_1.log)(`[VISOR] Saving screenshot: ${path}`);
537
539
  await (0, screen_1.saveScreenshot)(path);
538
- console.log("[VISOR] Screenshot saved");
540
+ (0, logger_1.log)("[VISOR] Screenshot saved");
539
541
  }
540
542
  /**
541
- * Opens a desktop application,
542
- * executable, file, folder,
543
- * or URL using Windows shell.
544
- *
545
- * Performance Note:
546
- * Some Electron-based applications
547
- * may require additional startup
548
- * stabilization time.
549
- *
550
- * @param command App name, executable,
551
- * file path, or URL.
552
- *
553
- * @example
554
- * await visor.openApp("notepad");
555
- *
556
- * @example
557
- * await visor.openApp("chrome.exe");
558
- */
543
+ * Opens a desktop application,
544
+ * executable, file, folder,
545
+ * or URL using Windows shell.
546
+ *
547
+ * Performance Note:
548
+ * Some Electron-based applications
549
+ * may require additional startup
550
+ * stabilization time.
551
+ *
552
+ * @param command App name, executable,
553
+ * file path, or URL.
554
+ *
555
+ * @example
556
+ * await visor.openApp("notepad");
557
+ *
558
+ * @example
559
+ * await visor.openApp("chrome.exe");
560
+ */
559
561
  async openApp(command) {
560
- console.log(`[VISOR] Opening app: ${command}`);
562
+ (0, logger_1.log)(`[VISOR] Opening app: ${command}`);
561
563
  await (0, app_1.openApp)(command);
562
564
  }
563
565
  /**
564
- * Drags one visual element and
565
- * drops it onto another using
566
- * image matching.
567
- *
568
- * @param source Source image.
569
- *
570
- * @param target Target image.
571
- *
572
- * @param confidence Match confidence threshold.
573
- *
574
- * Accepted range:
575
- * 0.0 to 1.0
576
- *
577
- * Default:
578
- * 0.8
579
- *
580
- * Recommended values:
581
- * - 0.7 for dynamic UI
582
- * - 0.8 for standard usage
583
- * - 0.9+ for strict matching
584
- *
585
- * @throws Error if source or target
586
- * image is not found.
587
- *
588
- * @example
589
- * await visor.dragDrop(
590
- * "file.png",
591
- * "folder.png"
592
- * );
593
- */
566
+ * Drags one visual element and
567
+ * drops it onto another using
568
+ * image matching.
569
+ *
570
+ * @param source Source image.
571
+ *
572
+ * @param target Target image.
573
+ *
574
+ * @param confidence Match confidence threshold.
575
+ *
576
+ * Accepted range:
577
+ * 0.0 to 1.0
578
+ *
579
+ * Default:
580
+ * 0.8
581
+ *
582
+ * Recommended values:
583
+ * - 0.7 for dynamic UI
584
+ * - 0.8 for standard usage
585
+ * - 0.9+ for strict matching
586
+ *
587
+ * @throws Error if source or target
588
+ * image is not found.
589
+ *
590
+ * @example
591
+ * await visor.dragDrop(
592
+ * "file.png",
593
+ * "folder.png"
594
+ * );
595
+ */
594
596
  async dragDrop(source, target, confidence = 0.8) {
595
597
  const src = await this.find(source, confidence);
596
598
  const dst = await this.find(target, confidence);
@@ -601,307 +603,314 @@ CONF:${m.confidence.toFixed(3)}
601
603
  await this.mouse.pressButton(this.Button.LEFT);
602
604
  await (0, mouse_1.moveToRegion)(dst);
603
605
  await this.mouse.releaseButton(this.Button.LEFT);
604
- console.log("[MOUSE] Drag and drop completed");
606
+ (0, logger_1.log)("[MOUSE] Drag and drop completed");
605
607
  }
606
608
  /**
607
- * Moves the mouse cursor to the
608
- * matched image location without
609
- * performing a click.
610
- *
611
- * @param image Image filename or path.
612
- * @param confidence Match confidence threshold.
613
- *
614
- * Accepted range:
615
- * 0.0 to 1.0
616
- *
617
- * Default:
618
- * 0.8
619
- *
620
- * @throws Error if image is not found.
621
- *
622
- * @example
623
- * await visor.hover("menu.png");
624
- */
609
+ * Moves the mouse cursor to the
610
+ * matched image location without
611
+ * performing a click.
612
+ *
613
+ * @param image Image filename or path.
614
+ * @param confidence Match confidence threshold.
615
+ *
616
+ * Accepted range:
617
+ * 0.0 to 1.0
618
+ *
619
+ * Default:
620
+ * 0.8
621
+ *
622
+ * @throws Error if image is not found.
623
+ *
624
+ * @example
625
+ * await visor.hover("menu.png");
626
+ */
625
627
  async hover(image, confidence = 0.8) {
626
628
  const region = await this.find(image, confidence);
627
629
  if (!region) {
628
630
  throw new Error(`Image not found: ${image}`);
629
631
  }
630
632
  await (0, mouse_1.moveToRegion)(region);
631
- console.log("[MOUSE] Hover completed");
633
+ (0, logger_1.log)("[MOUSE] Hover completed");
632
634
  }
633
635
  /**
634
- * Scrolls the mouse wheel downward.
635
- *
636
- * @param amount Scroll amount.
637
- *
638
- * Default:
639
- * 500
640
- *
641
- * Recommended range:
642
- * 100 to 3000
643
- *
644
- * @example
645
- * await visor.scrollDown(1000);
646
- */
636
+ * Scrolls the mouse wheel downward.
637
+ *
638
+ * @param amount Scroll amount.
639
+ *
640
+ * Default:
641
+ * 500
642
+ *
643
+ * Recommended range:
644
+ * 100 to 3000
645
+ *
646
+ * @example
647
+ * await visor.scrollDown(1000);
648
+ */
647
649
  async scrollDown(amount = 500) {
648
650
  await this.mouse.scrollDown(amount);
649
651
  }
650
652
  /**
651
- * Scrolls the mouse wheel upward.
652
- *
653
- * @param amount Scroll amount.
654
- *
655
- * Default:
656
- * 500
657
- *
658
- * Recommended range:
659
- * 100 to 3000
660
- *
661
- * @example
662
- * await visor.scrollUp(1000);
663
- */
653
+ * Scrolls the mouse wheel upward.
654
+ *
655
+ * @param amount Scroll amount.
656
+ *
657
+ * Default:
658
+ * 500
659
+ *
660
+ * Recommended range:
661
+ * 100 to 3000
662
+ *
663
+ * @example
664
+ * await visor.scrollUp(1000);
665
+ */
664
666
  async scrollUp(amount = 500) {
665
667
  await this.mouse.scrollUp(amount);
666
668
  }
667
669
  /**
668
- * Types text using keyboard automation.
669
- *
670
- * @param text Text to type.
671
- *
672
- * @example
673
- * await visor.type("Hello World");
674
- */
670
+ * Types text using keyboard automation.
671
+ *
672
+ * @param text Text to type.
673
+ *
674
+ * @example
675
+ * await visor.type("Hello World");
676
+ */
675
677
  async type(text) {
676
678
  await this.keyboard.type(text);
677
679
  }
678
680
  /**
679
- * Presses one or more keyboard keys.
680
- *
681
- * Supports both single key presses
682
- * and hotkey combinations.
683
- *
684
- * @param keys Keyboard keys to press.
685
- *
686
- * @example
687
- * await visor.press(visor.Key.Enter);
688
- *
689
- * @example
690
- * await visor.press(
691
- * visor.Key.LeftControl,
692
- * visor.Key.S
693
- * );
694
- */
681
+ * Presses one or more keyboard keys.
682
+ *
683
+ * Supports both single key presses
684
+ * and hotkey combinations.
685
+ *
686
+ * @param keys Keyboard keys to press.
687
+ *
688
+ * @example
689
+ * await visor.press(visor.Key.Enter);
690
+ *
691
+ * @example
692
+ * await visor.press(
693
+ * visor.Key.LeftControl,
694
+ * visor.Key.S
695
+ * );
696
+ */
695
697
  async press(...keys) {
696
698
  await this.keyboard.pressKey(...keys);
697
699
  await this.keyboard.releaseKey(...keys);
698
700
  }
699
701
  /**
700
- * Pauses execution for a specified
701
- * duration.
702
- *
703
- * Useful for:
704
- * - UI stabilization
705
- * - animation completion
706
- * - Electron rendering delays
707
- * - OCR synchronization
708
- * - desktop transition handling
709
- *
710
- * Recommended for short stabilization
711
- * waits rather than long fixed delays.
712
- *
713
- * @param ms Delay duration
714
- * in milliseconds.
715
- *
716
- * Recommended range:
717
- * 200ms to 5000ms
718
- *
719
- * Excessive sleep usage may
720
- * slow automation execution.
721
- *
722
- * @example
723
- * await visor.sleep(2000);
724
- */
702
+ * Pauses execution for a specified
703
+ * duration.
704
+ *
705
+ * Useful for:
706
+ * - UI stabilization
707
+ * - animation completion
708
+ * - Electron rendering delays
709
+ * - OCR synchronization
710
+ * - desktop transition handling
711
+ *
712
+ * Recommended for short stabilization
713
+ * waits rather than long fixed delays.
714
+ *
715
+ * @param ms Delay duration
716
+ * in milliseconds.
717
+ *
718
+ * Recommended range:
719
+ * 200ms to 5000ms
720
+ *
721
+ * Excessive sleep usage may
722
+ * slow automation execution.
723
+ *
724
+ * @example
725
+ * await visor.sleep(2000);
726
+ */
725
727
  async sleep(ms) {
726
- return new Promise(r => setTimeout(r, ms));
728
+ return new Promise((r) => setTimeout(r, ms));
727
729
  }
728
730
  /**
729
- * Moves the mouse cursor to the
730
- * specified screen coordinates.
731
- *
732
- * Coordinates should match the
733
- * current display scaling setup.
734
- *
735
- * @param x X coordinate.
736
- * @param y Y coordinate.
737
- *
738
- * @example
739
- * await visor.moveMouse(500, 300);
740
- */
731
+ * Moves the mouse cursor to the
732
+ * specified screen coordinates.
733
+ *
734
+ * Coordinates should match the
735
+ * current display scaling setup.
736
+ *
737
+ * @param x X coordinate.
738
+ * @param y Y coordinate.
739
+ *
740
+ * @example
741
+ * await visor.moveMouse(500, 300);
742
+ */
741
743
  async moveMouse(x, y) {
742
744
  await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(x, y)));
743
745
  }
744
746
  /**
745
- * Returns the current mouse cursor
746
- * position.
747
- *
748
- * @returns Current mouse coordinates.
749
- *
750
- * @example
751
- * const pos =
752
- * await visor.getMousePosition();
753
- */
747
+ * Returns the current mouse cursor
748
+ * position.
749
+ *
750
+ * @returns Current mouse coordinates.
751
+ *
752
+ * @example
753
+ * const pos =
754
+ * await visor.getMousePosition();
755
+ */
754
756
  async getMousePosition() {
755
757
  return await this.mouse.getPosition();
756
758
  }
757
759
  /**
758
- * Sets the display scaling factor
759
- * used for coordinate normalization
760
- * and image matching.
761
- *
762
- * Required for:
763
- * - high-DPI displays
764
- * - Windows display scaling
765
- * - accurate mouse positioning
766
- * - reliable template matching
767
- *
768
- * Common values:
769
- * - 1.0 = 100% scaling
770
- * - 1.25 = 125% scaling
771
- * - 1.5 = 150% scaling
772
- * - 2.0 = 200% scaling
773
- *
774
- * Incorrect scaling values may cause:
775
- * - inaccurate clicks
776
- * - failed image matching
777
- * - incorrect OCR regions
778
- * - offset mouse movement
779
- *
780
- * @param scale Display scaling factor.
781
- *
782
- * Recommended range:
783
- * 1.0 to 2.0
784
- *
785
- * @example
786
- * visor.setScaleFactor(1.5);
787
- */
760
+ * Sets the display scaling factor
761
+ * used for coordinate normalization
762
+ * and image matching.
763
+ *
764
+ * Required for:
765
+ * - high-DPI displays
766
+ * - Windows display scaling
767
+ * - accurate mouse positioning
768
+ * - reliable template matching
769
+ *
770
+ * Common values:
771
+ * - 1.0 = 100% scaling
772
+ * - 1.25 = 125% scaling
773
+ * - 1.5 = 150% scaling
774
+ * - 2.0 = 200% scaling
775
+ *
776
+ * Incorrect scaling values may cause:
777
+ * - inaccurate clicks
778
+ * - failed image matching
779
+ * - incorrect OCR regions
780
+ * - offset mouse movement
781
+ *
782
+ * @param scale Display scaling factor.
783
+ *
784
+ * Recommended range:
785
+ * 1.0 to 2.0
786
+ *
787
+ * @example
788
+ * visor.setScaleFactor(1.5);
789
+ */
788
790
  setScaleFactor(scale) {
789
791
  config_1.visorConfig.scaleFactor = scale;
790
792
  }
791
793
  /**
792
- * Returns the current display
793
- * scaling factor.
794
- *
795
- * @returns Current scale factor.
796
- *
797
- * @example
798
- * const scale =
799
- * visor.getScaleFactor();
800
- */
794
+ * Returns the current display
795
+ * scaling factor.
796
+ *
797
+ * @returns Current scale factor.
798
+ *
799
+ * @example
800
+ * const scale =
801
+ * visor.getScaleFactor();
802
+ */
801
803
  getScaleFactor() {
802
804
  return config_1.visorConfig.scaleFactor;
803
805
  }
804
806
  /**
805
- * Enables or disables debug logging.
806
- *
807
- * @param mode Debug mode state.
808
- *
809
- * @example
810
- * visor.setDebug(true);
811
- */
807
+ * Enables or disables debug logging.
808
+ *
809
+ * @param mode Debug mode state.
810
+ *
811
+ * @example
812
+ * visor.setDebug(true);
813
+ */
812
814
  setDebug(mode) {
813
815
  config_1.visorConfig.debug = mode;
814
816
  }
815
817
  /**
816
- * Sets the default image search path
817
- * used for visual automation APIs.
818
- *
819
- * @param path Image directory path.
820
- *
821
- * @example
822
- * visor.setImagePath("./images");
823
- */
818
+ * Sets the default image search path
819
+ * used for visual automation APIs.
820
+ *
821
+ * @param path Image directory path.
822
+ *
823
+ * @example
824
+ * visor.setImagePath("./images");
825
+ */
824
826
  setImagePath(path) {
825
827
  config_1.visorConfig.imagePath = path;
826
828
  }
827
829
  /**
828
- * Returns the current default
829
- * image search path.
830
- *
831
- * @returns Image path.
832
- *
833
- * @example
834
- * const path =
835
- * visor.getImagePath();
836
- */
830
+ * Returns the current default
831
+ * image search path.
832
+ *
833
+ * @returns Image path.
834
+ *
835
+ * @example
836
+ * const path =
837
+ * visor.getImagePath();
838
+ */
837
839
  getImagePath() {
838
840
  return config_1.visorConfig.imagePath;
839
841
  }
840
842
  /**
841
- * Sets the default output path
842
- * used for visual automation APIs.
843
- *
844
- * @param path Output directory path.
845
- *
846
- * @example
847
- * visor.setOutputPath("./images");
848
- */
843
+ * Sets the default output path
844
+ * used for visual automation APIs.
845
+ *
846
+ * @param path Output directory path.
847
+ *
848
+ * @example
849
+ * visor.setOutputPath("./images");
850
+ */
849
851
  setOutputPath(path) {
850
852
  config_1.visorConfig.outputPath = path;
851
853
  }
852
854
  /**
853
- * Returns the current default
854
- * Output path.
855
- *
856
- * @returns Output path.
857
- *
858
- * @example
859
- * const path =
860
- * visor.getOutputPath();
861
- */
855
+ * Returns the current default
856
+ * Output path.
857
+ *
858
+ * @returns Output path.
859
+ *
860
+ * @example
861
+ * const path =
862
+ * visor.getOutputPath();
863
+ */
862
864
  getOutputPath() {
863
865
  return config_1.visorConfig.outputPath;
864
866
  }
865
867
  /**
866
- * Closes a desktop application
867
- * using Windows taskkill.
868
- *
869
- * @param processName Process executable name.
870
- *
871
- * @example
872
- * await visor.closeApp("notepad.exe");
873
- *
874
- * @example
875
- * await visor.closeApp("ms-teams.exe");
876
- */
868
+ * Closes a desktop application
869
+ * using Windows taskkill.
870
+ *
871
+ * @param processName Process executable name.
872
+ *
873
+ * @example
874
+ * await visor.closeApp("notepad.exe");
875
+ *
876
+ * @example
877
+ * await visor.closeApp("ms-teams.exe");
878
+ */
877
879
  async closeApp(processName) {
878
880
  await (0, app_1.closeApp)(processName);
879
881
  }
880
882
  /**
881
- * Loads multiple framework settings
882
- * at once from a configuration object.
883
- *
884
- * Useful for centralized framework
885
- * initialization and project setup.
886
- *
887
- * Supported settings:
888
- * - scaleFactor
889
- * - imagePath
890
- * - debug
891
- *
892
- * @param config Framework configuration object.
893
- *
894
- * @example
895
- * visor.loadConfig({
896
- * scaleFactor: 1.5,
897
- * imagePath: "./images",
898
- * debug: true
899
- * });
900
- */
883
+ * Loads multiple framework settings
884
+ * at once from a configuration object.
885
+ *
886
+ * Useful for centralized framework
887
+ * initialization and project setup.
888
+ *
889
+ * Supported settings:
890
+ * - scaleFactor
891
+ * - imagePath
892
+ * - ssOutputPath
893
+ * - debug
894
+ *
895
+ * @param config Framework configuration object.
896
+ *
897
+ * @example
898
+ * visor.loadConfig({
899
+ * scaleFactor: 1.5,
900
+ * imagePath: "./images",
901
+ * ssOutputPath: "./screenshots",
902
+ * debug: true
903
+ * });
904
+ */
901
905
  loadConfig(config) {
902
906
  if (config.scaleFactor !== undefined) {
903
907
  this.setScaleFactor(config.scaleFactor);
904
908
  }
909
+ else {
910
+ const detectedScale = (0, display_1.getWindowsScaleFactor)();
911
+ config_1.visorConfig.scaleFactor = detectedScale;
912
+ (0, logger_1.log)(`[VISOR] Auto-detected display scaling: ${detectedScale}`);
913
+ }
905
914
  if (config.imagePath) {
906
915
  this.setImagePath(config.imagePath);
907
916
  }
@@ -911,36 +920,36 @@ CONF:${m.confidence.toFixed(3)}
911
920
  if (config.debug !== undefined) {
912
921
  this.setDebug(config.debug);
913
922
  }
914
- console.log("[VISOR] Config loaded");
923
+ (0, logger_1.log)("[VISOR] Config loaded");
915
924
  }
916
925
  /**
917
- * Finds the first matching image
918
- * from a list of possible images.
919
- *
920
- * Useful for handling:
921
- * - light/dark themes
922
- * - UI variations
923
- * - multiple visual states
924
- *
925
- * @param images Array of image filenames or paths.
926
- * @param confidence Match confidence threshold.
927
- *
928
- * Accepted range:
929
- * 0.0 to 1.0
930
- *
931
- * Default:
932
- * 0.8
933
- *
934
- * @returns Object containing matched image
935
- * and region, or null if none matched.
936
- *
937
- * @example
938
- * const result =
939
- * await visor.findAny([
940
- * "chat-light.png",
941
- * "chat-dark.png"
942
- * ]);
943
- */
926
+ * Finds the first matching image
927
+ * from a list of possible images.
928
+ *
929
+ * Useful for handling:
930
+ * - light/dark themes
931
+ * - UI variations
932
+ * - multiple visual states
933
+ *
934
+ * @param images Array of image filenames or paths.
935
+ * @param confidence Match confidence threshold.
936
+ *
937
+ * Accepted range:
938
+ * 0.0 to 1.0
939
+ *
940
+ * Default:
941
+ * 0.8
942
+ *
943
+ * @returns Object containing matched image
944
+ * and region, or null if none matched.
945
+ *
946
+ * @example
947
+ * const result =
948
+ * await visor.findAny([
949
+ * "chat-light.png",
950
+ * "chat-dark.png"
951
+ * ]);
952
+ */
944
953
  async findAny(images, confidence = 0.8) {
945
954
  const screen = await (0, screen_1.captureScreen)();
946
955
  try {
@@ -951,7 +960,7 @@ CONF:${m.confidence.toFixed(3)}
951
960
  if (region) {
952
961
  return {
953
962
  image,
954
- region
963
+ region,
955
964
  };
956
965
  }
957
966
  }
@@ -966,138 +975,138 @@ CONF:${m.confidence.toFixed(3)}
966
975
  }
967
976
  }
968
977
  /**
969
- * Checks whether any image from
970
- * a list exists on the current screen.
971
- *
972
- * Useful for handling:
973
- * - multiple themes
974
- * - alternate UI layouts
975
- * - dynamic visual states
976
- *
977
- * @param images Array of image filenames or paths.
978
- * @param confidence Match confidence threshold.
979
- *
980
- * Accepted range:
981
- * 0.0 to 1.0
982
- *
983
- * Default:
984
- * 0.8
985
- *
986
- * @returns True if any image exists.
987
- *
988
- * @example
989
- * const exists =
990
- * await visor.existsAny([
991
- * "save-light.png",
992
- * "save-dark.png"
993
- * ]);
994
- */
978
+ * Checks whether any image from
979
+ * a list exists on the current screen.
980
+ *
981
+ * Useful for handling:
982
+ * - multiple themes
983
+ * - alternate UI layouts
984
+ * - dynamic visual states
985
+ *
986
+ * @param images Array of image filenames or paths.
987
+ * @param confidence Match confidence threshold.
988
+ *
989
+ * Accepted range:
990
+ * 0.0 to 1.0
991
+ *
992
+ * Default:
993
+ * 0.8
994
+ *
995
+ * @returns True if any image exists.
996
+ *
997
+ * @example
998
+ * const exists =
999
+ * await visor.existsAny([
1000
+ * "save-light.png",
1001
+ * "save-dark.png"
1002
+ * ]);
1003
+ */
995
1004
  async existsAny(images, confidence = 0.8) {
996
1005
  return (await this.findAny(images, confidence)) !== null;
997
1006
  }
998
1007
  /**
999
- * Finds the first matching image
1000
- * from a list and performs a
1001
- * left mouse click on it.
1002
- *
1003
- * Useful for handling:
1004
- * - light/dark themes
1005
- * - UI variations
1006
- * - dynamic buttons/icons
1007
- *
1008
- * @param images Array of image
1009
- * filenames or paths.
1010
- *
1011
- * @param confidence Match confidence threshold.
1012
- *
1013
- * Accepted range:
1014
- * 0.0 to 1.0
1015
- *
1016
- * Default:
1017
- * 0.8
1018
- *
1019
- * Recommended values:
1020
- * - 0.7 for dynamic UI
1021
- * - 0.8 for standard usage
1022
- * - 0.9+ for strict matching
1023
- *
1024
- * Lower confidence increases
1025
- * flexibility but may increase
1026
- * false positives.
1027
- *
1028
- * @throws Error if none of the
1029
- * images are found.
1030
- *
1031
- * @example
1032
- * await visor.clickAny([
1033
- * "send-light.png",
1034
- * "send-dark.png"
1035
- * ]);
1036
- */
1008
+ * Finds the first matching image
1009
+ * from a list and performs a
1010
+ * left mouse click on it.
1011
+ *
1012
+ * Useful for handling:
1013
+ * - light/dark themes
1014
+ * - UI variations
1015
+ * - dynamic buttons/icons
1016
+ *
1017
+ * @param images Array of image
1018
+ * filenames or paths.
1019
+ *
1020
+ * @param confidence Match confidence threshold.
1021
+ *
1022
+ * Accepted range:
1023
+ * 0.0 to 1.0
1024
+ *
1025
+ * Default:
1026
+ * 0.8
1027
+ *
1028
+ * Recommended values:
1029
+ * - 0.7 for dynamic UI
1030
+ * - 0.8 for standard usage
1031
+ * - 0.9+ for strict matching
1032
+ *
1033
+ * Lower confidence increases
1034
+ * flexibility but may increase
1035
+ * false positives.
1036
+ *
1037
+ * @throws Error if none of the
1038
+ * images are found.
1039
+ *
1040
+ * @example
1041
+ * await visor.clickAny([
1042
+ * "send-light.png",
1043
+ * "send-dark.png"
1044
+ * ]);
1045
+ */
1037
1046
  async clickAny(images, confidence = 0.8) {
1038
1047
  const result = await this.findAny(images, confidence);
1039
1048
  if (!result) {
1040
1049
  throw new Error(`None of the images were found`);
1041
1050
  }
1042
- console.log(`[VISOR] Clicking image: ${result.image}`);
1051
+ (0, logger_1.log)(`[VISOR] Clicking image: ${result.image}`);
1043
1052
  await (0, mouse_1.clickRegion)(result.region);
1044
1053
  }
1045
1054
  /**
1046
- * Waits until any image from
1047
- * a list appears on screen.
1048
- *
1049
- * Useful for handling:
1050
- * - multiple themes
1051
- * - alternate UI layouts
1052
- * - dynamic application states
1053
- *
1054
- * @param images Array of image
1055
- * filenames or paths.
1056
- *
1057
- * @param confidence Match confidence threshold.
1058
- *
1059
- * Accepted range:
1060
- * 0.0 to 1.0
1061
- *
1062
- * Default:
1063
- * 0.8
1064
- *
1065
- * Recommended values:
1066
- * - 0.7 for dynamic UI
1067
- * - 0.8 for standard usage
1068
- * - 0.9+ for strict matching
1069
- *
1070
- * Lower confidence increases
1071
- * flexibility but may increase
1072
- * false positives.
1073
- *
1074
- * @param timeout Timeout duration
1075
- * in milliseconds.
1076
- *
1077
- * Default:
1078
- * 5000ms
1079
- *
1080
- * Recommended range:
1081
- * 1000ms to 30000ms
1082
- *
1083
- * @throws Error if timeout occurs.
1084
- *
1085
- * @example
1086
- * await visor.waitAny([
1087
- * "home-light.png",
1088
- * "home-dark.png"
1089
- * ]);
1090
- */
1055
+ * Waits until any image from
1056
+ * a list appears on screen.
1057
+ *
1058
+ * Useful for handling:
1059
+ * - multiple themes
1060
+ * - alternate UI layouts
1061
+ * - dynamic application states
1062
+ *
1063
+ * @param images Array of image
1064
+ * filenames or paths.
1065
+ *
1066
+ * @param confidence Match confidence threshold.
1067
+ *
1068
+ * Accepted range:
1069
+ * 0.0 to 1.0
1070
+ *
1071
+ * Default:
1072
+ * 0.8
1073
+ *
1074
+ * Recommended values:
1075
+ * - 0.7 for dynamic UI
1076
+ * - 0.8 for standard usage
1077
+ * - 0.9+ for strict matching
1078
+ *
1079
+ * Lower confidence increases
1080
+ * flexibility but may increase
1081
+ * false positives.
1082
+ *
1083
+ * @param timeout Timeout duration
1084
+ * in milliseconds.
1085
+ *
1086
+ * Default:
1087
+ * 5000ms
1088
+ *
1089
+ * Recommended range:
1090
+ * 1000ms to 30000ms
1091
+ *
1092
+ * @throws Error if timeout occurs.
1093
+ *
1094
+ * @example
1095
+ * await visor.waitAny([
1096
+ * "home-light.png",
1097
+ * "home-dark.png"
1098
+ * ]);
1099
+ */
1091
1100
  async waitAny(images, { confidence = 0.8, timeout = 5000 } = {}) {
1092
- const interval = 1000;
1101
+ const interval = 300;
1093
1102
  const attempts = Math.ceil(timeout / interval);
1094
1103
  for (let i = 0; i < attempts; i++) {
1095
- console.log(`[WAITANY] Attempt ${i + 1}`);
1104
+ (0, logger_1.log)(`[WAITANY] Attempt ${i + 1}`);
1096
1105
  for (const image of images) {
1097
- console.log(`[WAITANY] Checking ${image}`);
1106
+ (0, logger_1.log)(`[WAITANY] Checking ${image}`);
1098
1107
  const exists = await this.exists(image, confidence);
1099
1108
  if (exists) {
1100
- console.log(`[WAITANY] Found ${image}`);
1109
+ (0, logger_1.log)(`[WAITANY] Found ${image}`);
1101
1110
  return true;
1102
1111
  }
1103
1112
  }
@@ -1106,18 +1115,18 @@ CONF:${m.confidence.toFixed(3)}
1106
1115
  throw new Error("Timeout waiting for images");
1107
1116
  }
1108
1117
  /**
1109
- * Terminates shared OCR worker.
1110
- *
1111
- * Useful for framework cleanup
1112
- * after long automation sessions.
1113
- *
1114
- * Recommended for:
1115
- * - long-running automation
1116
- * - memory cleanup
1117
- * - graceful framework shutdown
1118
- * @example
1119
- * await visor.terminateOCR();
1120
- */
1118
+ * Terminates shared OCR worker.
1119
+ *
1120
+ * Useful for framework cleanup
1121
+ * after long automation sessions.
1122
+ *
1123
+ * Recommended for:
1124
+ * - long-running automation
1125
+ * - memory cleanup
1126
+ * - graceful framework shutdown
1127
+ * @example
1128
+ * await visor.terminateOCR();
1129
+ */
1121
1130
  async terminateOCR() {
1122
1131
  await (0, ocr_1.terminateOCR)();
1123
1132
  }