stelo 1.0.1

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.
Files changed (141) hide show
  1. package/LICENSE +184 -0
  2. package/README.md +853 -0
  3. package/dist/accessibility.d.ts +227 -0
  4. package/dist/accessibility.d.ts.map +1 -0
  5. package/dist/accessibility.js +602 -0
  6. package/dist/accessibility.js.map +1 -0
  7. package/dist/agent.d.ts +870 -0
  8. package/dist/agent.d.ts.map +1 -0
  9. package/dist/agent.js +1107 -0
  10. package/dist/agent.js.map +1 -0
  11. package/dist/audio-stream.d.ts +114 -0
  12. package/dist/audio-stream.d.ts.map +1 -0
  13. package/dist/audio-stream.js +167 -0
  14. package/dist/audio-stream.js.map +1 -0
  15. package/dist/clipboard.d.ts +99 -0
  16. package/dist/clipboard.d.ts.map +1 -0
  17. package/dist/clipboard.js +352 -0
  18. package/dist/clipboard.js.map +1 -0
  19. package/dist/config.d.ts +183 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +477 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/context.d.ts +213 -0
  24. package/dist/context.d.ts.map +1 -0
  25. package/dist/context.js +387 -0
  26. package/dist/context.js.map +1 -0
  27. package/dist/cortex.d.ts +548 -0
  28. package/dist/cortex.d.ts.map +1 -0
  29. package/dist/cortex.js +1479 -0
  30. package/dist/cortex.js.map +1 -0
  31. package/dist/errors.d.ts +133 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +278 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/events.d.ts +227 -0
  36. package/dist/events.d.ts.map +1 -0
  37. package/dist/events.js +429 -0
  38. package/dist/events.js.map +1 -0
  39. package/dist/executor.d.ts +212 -0
  40. package/dist/executor.d.ts.map +1 -0
  41. package/dist/executor.js +545 -0
  42. package/dist/executor.js.map +1 -0
  43. package/dist/index.d.ts +69 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +167 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/integration.d.ts +159 -0
  48. package/dist/integration.d.ts.map +1 -0
  49. package/dist/integration.js +533 -0
  50. package/dist/integration.js.map +1 -0
  51. package/dist/keyboard.d.ts +276 -0
  52. package/dist/keyboard.d.ts.map +1 -0
  53. package/dist/keyboard.js +404 -0
  54. package/dist/keyboard.js.map +1 -0
  55. package/dist/logger.d.ts +198 -0
  56. package/dist/logger.d.ts.map +1 -0
  57. package/dist/logger.js +516 -0
  58. package/dist/logger.js.map +1 -0
  59. package/dist/middleware.d.ts +183 -0
  60. package/dist/middleware.d.ts.map +1 -0
  61. package/dist/middleware.js +493 -0
  62. package/dist/middleware.js.map +1 -0
  63. package/dist/monitor.d.ts +136 -0
  64. package/dist/monitor.d.ts.map +1 -0
  65. package/dist/monitor.js +341 -0
  66. package/dist/monitor.js.map +1 -0
  67. package/dist/mouse.d.ts +290 -0
  68. package/dist/mouse.d.ts.map +1 -0
  69. package/dist/mouse.js +466 -0
  70. package/dist/mouse.js.map +1 -0
  71. package/dist/plugin.d.ts +157 -0
  72. package/dist/plugin.d.ts.map +1 -0
  73. package/dist/plugin.js +409 -0
  74. package/dist/plugin.js.map +1 -0
  75. package/dist/process.d.ts +106 -0
  76. package/dist/process.d.ts.map +1 -0
  77. package/dist/process.js +326 -0
  78. package/dist/process.js.map +1 -0
  79. package/dist/recorder.d.ts +100 -0
  80. package/dist/recorder.d.ts.map +1 -0
  81. package/dist/recorder.js +258 -0
  82. package/dist/recorder.js.map +1 -0
  83. package/dist/safety.d.ts +59 -0
  84. package/dist/safety.d.ts.map +1 -0
  85. package/dist/safety.js +98 -0
  86. package/dist/safety.js.map +1 -0
  87. package/dist/scheduler.d.ts +152 -0
  88. package/dist/scheduler.d.ts.map +1 -0
  89. package/dist/scheduler.js +615 -0
  90. package/dist/scheduler.js.map +1 -0
  91. package/dist/screen.d.ts +96 -0
  92. package/dist/screen.d.ts.map +1 -0
  93. package/dist/screen.js +154 -0
  94. package/dist/screen.js.map +1 -0
  95. package/dist/session.d.ts +209 -0
  96. package/dist/session.d.ts.map +1 -0
  97. package/dist/session.js +479 -0
  98. package/dist/session.js.map +1 -0
  99. package/dist/stream.d.ts +168 -0
  100. package/dist/stream.d.ts.map +1 -0
  101. package/dist/stream.js +298 -0
  102. package/dist/stream.js.map +1 -0
  103. package/dist/telemetry.d.ts +223 -0
  104. package/dist/telemetry.d.ts.map +1 -0
  105. package/dist/telemetry.js +433 -0
  106. package/dist/telemetry.js.map +1 -0
  107. package/dist/types.d.ts +165 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +8 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/utils/bezier.d.ts +51 -0
  112. package/dist/utils/bezier.d.ts.map +1 -0
  113. package/dist/utils/bezier.js +117 -0
  114. package/dist/utils/bezier.js.map +1 -0
  115. package/dist/utils/helpers.d.ts +90 -0
  116. package/dist/utils/helpers.d.ts.map +1 -0
  117. package/dist/utils/helpers.js +143 -0
  118. package/dist/utils/helpers.js.map +1 -0
  119. package/dist/utils/index.d.ts +4 -0
  120. package/dist/utils/index.d.ts.map +1 -0
  121. package/dist/utils/index.js +18 -0
  122. package/dist/utils/index.js.map +1 -0
  123. package/dist/validation.d.ts +254 -0
  124. package/dist/validation.d.ts.map +1 -0
  125. package/dist/validation.js +478 -0
  126. package/dist/validation.js.map +1 -0
  127. package/dist/vision.d.ts +719 -0
  128. package/dist/vision.d.ts.map +1 -0
  129. package/dist/vision.js +1197 -0
  130. package/dist/vision.js.map +1 -0
  131. package/dist/window.d.ts +80 -0
  132. package/dist/window.d.ts.map +1 -0
  133. package/dist/window.js +170 -0
  134. package/dist/window.js.map +1 -0
  135. package/dist/workflow.d.ts +224 -0
  136. package/dist/workflow.d.ts.map +1 -0
  137. package/dist/workflow.js +578 -0
  138. package/dist/workflow.js.map +1 -0
  139. package/index.d.ts +840 -0
  140. package/index.js +495 -0
  141. package/package.json +91 -0
package/dist/agent.js ADDED
@@ -0,0 +1,1107 @@
1
+ "use strict";
2
+ /**
3
+ * Real-time Agent Control Module
4
+ *
5
+ * Designed for low-latency control of mouse and keyboard with:
6
+ * - Action batching (minimizes round-trips)
7
+ * - Visual verification (confirms actions had effect)
8
+ * - Async non-blocking movement (cursor moves visually in real-time)
9
+ * - Parallel action execution (multiple things at once)
10
+ * - Streaming cursor control (continuous, cancellable)
11
+ * - Velocity-based streaming control (continuous, low-latency)
12
+ * - Gesture recording and playback
13
+ *
14
+ * @module agent
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.agent = exports.ActionSequence = void 0;
18
+ exports.executeBatch = executeBatch;
19
+ exports.clickAndVerify = clickAndVerify;
20
+ exports.hotkeyAndVerify = hotkeyAndVerify;
21
+ exports.moveRelative = moveRelative;
22
+ exports.moveRelativeSmooth = moveRelativeSmooth;
23
+ exports.typeAndWaitStable = typeAndWaitStable;
24
+ exports.recordMouseTrail = recordMouseTrail;
25
+ exports.replayMouseTrail = replayMouseTrail;
26
+ exports.releaseAllModifiers = releaseAllModifiers;
27
+ exports.sequence = sequence;
28
+ exports.clickAndWait = clickAndWait;
29
+ exports.typeAndEnter = typeAndEnter;
30
+ exports.parallel = parallel;
31
+ exports.createCursorStream = createCursorStream;
32
+ exports.moveClickVerify = moveClickVerify;
33
+ exports.executeBatchAsync = executeBatchAsync;
34
+ exports.smoothClickAt = smoothClickAt;
35
+ exports.smoothClickAndType = smoothClickAndType;
36
+ exports.nativeParallel = nativeParallel;
37
+ exports.interleave = interleave;
38
+ exports.ocr = ocr;
39
+ exports.findText = findText;
40
+ exports.clickText = clickText;
41
+ exports.waitForText = waitForText;
42
+ exports.waitForTextAndClick = waitForTextAndClick;
43
+ exports.watchRegion = watchRegion;
44
+ exports.onRegionChange = onRegionChange;
45
+ exports.onHotkey = onHotkey;
46
+ exports.waitForHotkey = waitForHotkey;
47
+ const index_js_1 = require("../index.js");
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+ // Core Functions
50
+ // ─────────────────────────────────────────────────────────────────────────────
51
+ /**
52
+ * Execute multiple actions as an atomic batch.
53
+ *
54
+ * This is the primary way applications should interact with the system.
55
+ * All actions execute sequentially in a single native call,
56
+ * minimizing latency and round-trips.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // Click a button, wait for response, then type
61
+ * const result = await agent.executeBatch([
62
+ * { type: 'mouseClickAt', x: 500, y: 300 },
63
+ * { type: 'waitForStable', stableMs: 200 },
64
+ * { type: 'type', text: 'Hello World' },
65
+ * { type: 'keyPress', key: 'Enter' }
66
+ * ]);
67
+ *
68
+ * if (result.allSucceeded) {
69
+ * console.log('All actions completed in', result.totalDurationMs, 'ms');
70
+ * }
71
+ * ```
72
+ *
73
+ * @param actions Array of actions to execute
74
+ * @param options Execution options
75
+ * @returns Batch result with per-action details
76
+ */
77
+ function executeBatch(actions, options = {}) {
78
+ const nativeResult = (0, index_js_1.agentExecuteBatch)(actions, options.stopOnError ?? true);
79
+ return {
80
+ results: nativeResult.results.map((r) => ({
81
+ index: r.index,
82
+ success: r.success,
83
+ error: r.error ?? undefined,
84
+ durationMs: r.durationMs,
85
+ mousePosition: r.mouseX != null && r.mouseY != null
86
+ ? { x: r.mouseX, y: r.mouseY }
87
+ : undefined,
88
+ changeDetected: r.changeDetected ?? undefined,
89
+ })),
90
+ totalDurationMs: nativeResult.totalDurationMs,
91
+ successCount: nativeResult.successCount,
92
+ failureCount: nativeResult.failureCount,
93
+ firstFailureIndex: nativeResult.firstFailureIndex,
94
+ allSucceeded: nativeResult.allSucceeded,
95
+ };
96
+ }
97
+ /**
98
+ * Click at a position and verify visual change occurred.
99
+ *
100
+ * Useful for confirming clicks had an effect.
101
+ * Captures screen before and after click, computes diff.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const result = await agent.clickAndVerify(500, 300);
106
+ * if (!result.verified) {
107
+ * console.log('Click had no visual effect - may need retry');
108
+ * }
109
+ * ```
110
+ *
111
+ * @param x Target X coordinate
112
+ * @param y Target Y coordinate
113
+ * @param options Click options
114
+ * @returns Verification result
115
+ */
116
+ function clickAndVerify(x, y, options = {}) {
117
+ const result = (0, index_js_1.agentClickAndVerify)(x, y, options.button, options.minChangePercent, options.timeoutMs, options.region?.x, options.region?.y, options.region?.width, options.region?.height);
118
+ return {
119
+ verified: result.verified,
120
+ changePercentage: result.changePercentage,
121
+ durationMs: result.durationMs,
122
+ };
123
+ }
124
+ /**
125
+ * Execute a hotkey combination and verify visual change.
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // Open file dialog and verify it appeared
130
+ * const result = await agent.hotkeyAndVerify(['ctrl', 'o']);
131
+ * if (result.verified) {
132
+ * console.log('Dialog opened');
133
+ * }
134
+ * ```
135
+ *
136
+ * @param keys Array of keys to press together
137
+ * @param options Verification options
138
+ * @returns Verification result
139
+ */
140
+ function hotkeyAndVerify(keys, options = {}) {
141
+ const result = (0, index_js_1.agentHotkeyAndVerify)(keys, options.minChangePercent, options.timeoutMs, options.region?.x, options.region?.y, options.region?.width, options.region?.height);
142
+ return {
143
+ verified: result.verified,
144
+ changePercentage: result.changePercentage,
145
+ durationMs: result.durationMs,
146
+ };
147
+ }
148
+ // ─────────────────────────────────────────────────────────────────────────────
149
+ // Relative Mouse Movement
150
+ // ─────────────────────────────────────────────────────────────────────────────
151
+ /**
152
+ * Move mouse relative to current position.
153
+ *
154
+ * @param dx Horizontal offset (positive = right)
155
+ * @param dy Vertical offset (positive = down)
156
+ * @returns New mouse position
157
+ */
158
+ function moveRelative(dx, dy) {
159
+ const pos = (0, index_js_1.agentMoveRelative)(dx, dy);
160
+ return { x: pos.x, y: pos.y };
161
+ }
162
+ /**
163
+ * Move mouse relative to current position with smooth animation.
164
+ *
165
+ * @param dx Horizontal offset
166
+ * @param dy Vertical offset
167
+ * @param durationMs Animation duration (default: 300ms)
168
+ * @returns New mouse position
169
+ */
170
+ function moveRelativeSmooth(dx, dy, durationMs) {
171
+ const pos = (0, index_js_1.agentMoveRelativeSmooth)(dx, dy, durationMs);
172
+ return { x: pos.x, y: pos.y };
173
+ }
174
+ // ─────────────────────────────────────────────────────────────────────────────
175
+ // Text Input with Verification
176
+ // ─────────────────────────────────────────────────────────────────────────────
177
+ /**
178
+ * Type text and wait for screen to stabilize.
179
+ *
180
+ * Useful for form input where you want to wait for
181
+ * autocomplete or validation to finish.
182
+ *
183
+ * @param text Text to type
184
+ * @param options Wait options
185
+ * @returns True if screen stabilized within timeout
186
+ */
187
+ function typeAndWaitStable(text, options = {}) {
188
+ return (0, index_js_1.agentTypeAndWaitStable)(text, options.stabilityThreshold, options.stableDurationMs, options.timeoutMs);
189
+ }
190
+ // ─────────────────────────────────────────────────────────────────────────────
191
+ // Gesture Recording
192
+ // ─────────────────────────────────────────────────────────────────────────────
193
+ /**
194
+ * Record mouse movements for a duration.
195
+ *
196
+ * Captures mouse trail for gesture analysis or replay.
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * // Record 3 seconds of mouse movement
201
+ * const trail = agent.recordMouseTrail(3000);
202
+ * console.log(`Recorded ${trail.length} points`);
203
+ *
204
+ * // Replay at half speed
205
+ * agent.replayMouseTrail(trail, 0.5);
206
+ * ```
207
+ *
208
+ * @param durationMs How long to record
209
+ * @param sampleRateHz Sample rate (default: 60)
210
+ * @returns Array of trail points with timestamps
211
+ */
212
+ function recordMouseTrail(durationMs, sampleRateHz) {
213
+ const trail = (0, index_js_1.agentRecordMouseTrail)(durationMs, sampleRateHz);
214
+ return trail.map((p) => ({
215
+ timestampMs: p.timestampMs,
216
+ x: p.x,
217
+ y: p.y,
218
+ }));
219
+ }
220
+ /**
221
+ * Replay a recorded mouse trail.
222
+ *
223
+ * @param trail Previously recorded trail
224
+ * @param speedMultiplier Playback speed (1.0 = normal, 0.5 = half speed)
225
+ */
226
+ function replayMouseTrail(trail, speedMultiplier) {
227
+ const native = trail.map((p) => ({
228
+ timestampMs: p.timestampMs,
229
+ x: p.x,
230
+ y: p.y,
231
+ }));
232
+ (0, index_js_1.agentReplayMouseTrail)(native, speedMultiplier);
233
+ }
234
+ // ─────────────────────────────────────────────────────────────────────────────
235
+ // Error Recovery
236
+ // ─────────────────────────────────────────────────────────────────────────────
237
+ /**
238
+ * Release all held modifier keys.
239
+ *
240
+ * Call this for error recovery when modifier keys might be stuck,
241
+ * or after complex keyboard sequences.
242
+ */
243
+ function releaseAllModifiers() {
244
+ (0, index_js_1.agentReleaseAllModifiers)();
245
+ }
246
+ // ─────────────────────────────────────────────────────────────────────────────
247
+ // Action Builders (Fluent API)
248
+ // ─────────────────────────────────────────────────────────────────────────────
249
+ /**
250
+ * Fluent action builder for creating complex sequences.
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const result = agent.sequence()
255
+ * .click(500, 300)
256
+ * .waitForStable()
257
+ * .type('Hello World')
258
+ * .press('Enter')
259
+ * .waitForChange()
260
+ * .execute();
261
+ * ```
262
+ */
263
+ class ActionSequence {
264
+ actions = [];
265
+ /** Move mouse to absolute position */
266
+ moveTo(x, y) {
267
+ this.actions.push({ type: 'mouseMove', x, y });
268
+ return this;
269
+ }
270
+ /** Move mouse smoothly to absolute position */
271
+ moveToSmooth(x, y, duration) {
272
+ this.actions.push({ type: 'mouseMoveSmooth', x, y, duration });
273
+ return this;
274
+ }
275
+ /** Move mouse relative to current position */
276
+ moveBy(dx, dy) {
277
+ this.actions.push({ type: 'mouseMoveRel', dx, dy });
278
+ return this;
279
+ }
280
+ /** Click at current position */
281
+ click(button) {
282
+ this.actions.push({ type: 'mouseClick', button });
283
+ return this;
284
+ }
285
+ /** Click at specific coordinates */
286
+ clickAt(x, y, button) {
287
+ this.actions.push({ type: 'mouseClickAt', x, y, button });
288
+ return this;
289
+ }
290
+ /** Double click */
291
+ doubleClick(button) {
292
+ this.actions.push({ type: 'mouseDoubleClick', button });
293
+ return this;
294
+ }
295
+ /** Press mouse button down */
296
+ mouseDown(button) {
297
+ this.actions.push({ type: 'mouseDown', button });
298
+ return this;
299
+ }
300
+ /** Release mouse button */
301
+ mouseUp(button) {
302
+ this.actions.push({ type: 'mouseUp', button });
303
+ return this;
304
+ }
305
+ /** Scroll wheel */
306
+ scroll(amount, horizontal) {
307
+ this.actions.push({ type: 'mouseScroll', amount, horizontal });
308
+ return this;
309
+ }
310
+ /** Drag from current position to target */
311
+ dragTo(toX, toY, button) {
312
+ this.actions.push({ type: 'mouseDrag', toX, toY, button });
313
+ return this;
314
+ }
315
+ /** Type text instantly */
316
+ type(text) {
317
+ this.actions.push({ type: 'type', text });
318
+ return this;
319
+ }
320
+ /** Type text with human-like delays */
321
+ typeHuman(text, minDelay, maxDelay) {
322
+ this.actions.push({ type: 'typeHumanized', text, minDelay, maxDelay });
323
+ return this;
324
+ }
325
+ /** Press and release a key */
326
+ press(key) {
327
+ this.actions.push({ type: 'keyPress', key });
328
+ return this;
329
+ }
330
+ /** Press key down (remember to release!) */
331
+ keyDown(key) {
332
+ this.actions.push({ type: 'keyDown', key });
333
+ return this;
334
+ }
335
+ /** Release key */
336
+ keyUp(key) {
337
+ this.actions.push({ type: 'keyUp', key });
338
+ return this;
339
+ }
340
+ /** Press a hotkey combination */
341
+ hotkey(...keys) {
342
+ this.actions.push({ type: 'hotkey', keys });
343
+ return this;
344
+ }
345
+ /** Wait for specified duration */
346
+ delay(ms) {
347
+ this.actions.push({ type: 'delay', ms });
348
+ return this;
349
+ }
350
+ /** Alias for delay */
351
+ wait(ms) {
352
+ return this.delay(ms);
353
+ }
354
+ /** Wait for visual change */
355
+ waitForChange(options) {
356
+ this.actions.push({
357
+ type: 'waitForChange',
358
+ threshold: options?.threshold,
359
+ timeout: options?.timeout,
360
+ region: options?.region,
361
+ });
362
+ return this;
363
+ }
364
+ /** Wait for screen to stabilize */
365
+ waitForStable(options) {
366
+ this.actions.push({
367
+ type: 'waitForStable',
368
+ threshold: options?.threshold,
369
+ stableMs: options?.stableMs,
370
+ timeout: options?.timeout,
371
+ region: options?.region,
372
+ });
373
+ return this;
374
+ }
375
+ /** Get the built actions array */
376
+ build() {
377
+ return [...this.actions];
378
+ }
379
+ /** Execute all queued actions */
380
+ execute(options) {
381
+ return executeBatch(this.actions, options);
382
+ }
383
+ /** Execute all queued actions — non-blocking async version */
384
+ async executeAsync(options) {
385
+ return executeBatchAsync(this.actions, options);
386
+ }
387
+ /** Clear all queued actions */
388
+ clear() {
389
+ this.actions = [];
390
+ return this;
391
+ }
392
+ }
393
+ exports.ActionSequence = ActionSequence;
394
+ /**
395
+ * Create a new action sequence builder.
396
+ *
397
+ * @example
398
+ * ```typescript
399
+ * const result = agent.sequence()
400
+ * .clickAt(500, 300)
401
+ * .waitForStable()
402
+ * .type('search query')
403
+ * .press('Enter')
404
+ * .execute();
405
+ * ```
406
+ */
407
+ function sequence() {
408
+ return new ActionSequence();
409
+ }
410
+ // ─────────────────────────────────────────────────────────────────────────────
411
+ // Convenience Functions
412
+ // ─────────────────────────────────────────────────────────────────────────────
413
+ /**
414
+ * Simple click with optional wait for visual feedback.
415
+ * Combines click and waitForStable in one call.
416
+ *
417
+ * @param x Target X coordinate
418
+ * @param y Target Y coordinate
419
+ * @param options Click options
420
+ * @returns Batch result
421
+ */
422
+ function clickAndWait(x, y, options = {}) {
423
+ return executeBatch([
424
+ { type: 'mouseClickAt', x, y, button: options.button },
425
+ { type: 'waitForStable', stableMs: options.stableMs ?? 200 },
426
+ ]);
427
+ }
428
+ /**
429
+ * Type text followed by Enter key.
430
+ *
431
+ * @param text Text to type before pressing Enter
432
+ * @param options Type options
433
+ * @returns Batch result
434
+ */
435
+ function typeAndEnter(text, options = {}) {
436
+ const actions = options.humanized
437
+ ? [{ type: 'typeHumanized', text }, { type: 'keyPress', key: 'Enter' }]
438
+ : [{ type: 'type', text }, { type: 'keyPress', key: 'Enter' }];
439
+ return executeBatch(actions);
440
+ }
441
+ /**
442
+ * Execute multiple independent actions in parallel.
443
+ *
444
+ * This is the key primitive for AI agents that need to do multiple things
445
+ * simultaneously — e.g., move the mouse while monitoring the screen,
446
+ * or type while watching for visual changes.
447
+ *
448
+ * Each task is a named async function. All run concurrently via Promise.all.
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * // Move mouse and monitor screen simultaneously
453
+ * const result = await agent.parallel({
454
+ * move: async () => {
455
+ * // Non-blocking smooth movement
456
+ * const handle = mouse.moveSmoothAsync(500, 300, { duration: 600 });
457
+ * return handle.promise;
458
+ * },
459
+ * monitor: async () => {
460
+ * // Capture screen while mouse is moving
461
+ * await sleep(200);
462
+ * return screen.capture();
463
+ * },
464
+ * });
465
+ *
466
+ * // All done
467
+ * console.log(result.allSucceeded); // true
468
+ * ```
469
+ */
470
+ async function parallel(tasks) {
471
+ const start = Date.now();
472
+ const names = Object.keys(tasks);
473
+ const promises = names.map(async (name) => {
474
+ const taskStart = Date.now();
475
+ try {
476
+ const value = await tasks[name]();
477
+ return {
478
+ name,
479
+ success: true,
480
+ durationMs: Date.now() - taskStart,
481
+ value,
482
+ };
483
+ }
484
+ catch (err) {
485
+ return {
486
+ name,
487
+ success: false,
488
+ error: err?.message ?? String(err),
489
+ durationMs: Date.now() - taskStart,
490
+ };
491
+ }
492
+ });
493
+ const results = await Promise.all(promises);
494
+ return {
495
+ results,
496
+ totalDurationMs: Date.now() - start,
497
+ allSucceeded: results.every(r => r.success),
498
+ };
499
+ }
500
+ /**
501
+ * Create a real-time cursor control stream.
502
+ *
503
+ * Returns a handle that lets you continuously direct the cursor in real-time.
504
+ * The cursor moves smoothly towards targets with no blocking. Multiple
505
+ * `moveTo()` calls seamlessly redirect the cursor mid-flight.
506
+ *
507
+ * This is the preferred way for AI agents to control the cursor because:
508
+ * - Movement is always visible and smooth
509
+ * - Targets can be updated any time (no waiting for previous move to finish)
510
+ * - Velocity-based control for continuous steering
511
+ * - Zero blocking of the Node.js event loop
512
+ *
513
+ * @param updateRateHz How many times per second to update position (default: 120)
514
+ *
515
+ * @example
516
+ * ```typescript
517
+ * const cursor = agent.createCursorStream(120);
518
+ *
519
+ * // Smooth movement to target
520
+ * cursor.moveTo(500, 300);
521
+ *
522
+ * // Change target mid-flight — cursor redirects smoothly
523
+ * setTimeout(() => cursor.moveTo(800, 600), 200);
524
+ *
525
+ * // Velocity-based control (e.g., from joystick or AI output)
526
+ * cursor.setVelocity(200, -100); // 200px/s right, 100px/s up
527
+ *
528
+ * // When done
529
+ * cursor.destroy();
530
+ * ```
531
+ */
532
+ function createCursorStream(updateRateHz = 120) {
533
+ let active = true;
534
+ let targetX = null;
535
+ let targetY = null;
536
+ let velocityX = 0;
537
+ let velocityY = 0;
538
+ let timer = null;
539
+ const intervalMs = Math.max(1, Math.round(1000 / updateRateHz));
540
+ // The update loop runs on a setInterval — non-blocking
541
+ timer = setInterval(() => {
542
+ if (!active)
543
+ return;
544
+ try {
545
+ const pos = (0, index_js_1.mouseGetPosition)();
546
+ if (targetX !== null && targetY !== null) {
547
+ const dx = targetX - pos.x;
548
+ const dy = targetY - pos.y;
549
+ const dist = Math.sqrt(dx * dx + dy * dy);
550
+ if (dist < 2) {
551
+ // Arrived at target
552
+ (0, index_js_1.mouseMove)(targetX, targetY);
553
+ targetX = null;
554
+ targetY = null;
555
+ }
556
+ else {
557
+ // Move towards target — speed proportional to distance
558
+ const speed = Math.min(3000, dist * 6);
559
+ const moveX = Math.round((dx / dist) * speed / updateRateHz);
560
+ const moveY = Math.round((dy / dist) * speed / updateRateHz);
561
+ (0, index_js_1.mouseMove)(pos.x + moveX, pos.y + moveY);
562
+ }
563
+ }
564
+ else if (velocityX !== 0 || velocityY !== 0) {
565
+ // Velocity-based movement
566
+ const moveX = Math.round(velocityX / updateRateHz);
567
+ const moveY = Math.round(velocityY / updateRateHz);
568
+ if (moveX !== 0 || moveY !== 0) {
569
+ (0, index_js_1.mouseMove)(pos.x + moveX, pos.y + moveY);
570
+ }
571
+ }
572
+ }
573
+ catch {
574
+ // Silently continue on error (e.g., if mouse API fails momentarily)
575
+ }
576
+ }, intervalMs);
577
+ const handle = {
578
+ moveTo(x, y) {
579
+ targetX = x;
580
+ targetY = y;
581
+ velocityX = 0;
582
+ velocityY = 0;
583
+ },
584
+ jumpTo(x, y) {
585
+ targetX = null;
586
+ targetY = null;
587
+ velocityX = 0;
588
+ velocityY = 0;
589
+ (0, index_js_1.mouseMove)(x, y);
590
+ },
591
+ setVelocity(vx, vy) {
592
+ velocityX = vx;
593
+ velocityY = vy;
594
+ targetX = null;
595
+ targetY = null;
596
+ },
597
+ stop() {
598
+ targetX = null;
599
+ targetY = null;
600
+ velocityX = 0;
601
+ velocityY = 0;
602
+ },
603
+ destroy() {
604
+ active = false;
605
+ if (timer !== null) {
606
+ clearInterval(timer);
607
+ timer = null;
608
+ }
609
+ },
610
+ get active() { return active; },
611
+ get position() {
612
+ const p = (0, index_js_1.mouseGetPosition)();
613
+ return { x: p.x, y: p.y };
614
+ },
615
+ };
616
+ return handle;
617
+ }
618
+ // ─────────────────────────────────────────────────────────────────────────────
619
+ // Non-Blocking Agent Primitives
620
+ // ─────────────────────────────────────────────────────────────────────────────
621
+ /**
622
+ * Move to a position smoothly, click, and verify — all non-blocking.
623
+ *
624
+ * The cursor visually moves to the target, clicks, then verifies
625
+ * that the screen changed. The entire operation is async.
626
+ *
627
+ * @example
628
+ * ```typescript
629
+ * const result = await agent.moveClickVerify(500, 300, {
630
+ * moveDuration: 400,
631
+ * button: 'left',
632
+ * });
633
+ * console.log(result.verified); // true if screen changed after click
634
+ * ```
635
+ */
636
+ async function moveClickVerify(x, y, options = {}) {
637
+ // Non-blocking smooth movement
638
+ const from = (0, index_js_1.mouseGetPosition)();
639
+ const duration = options.moveDuration ?? 400;
640
+ const steps = Math.max(2, Math.round((120 * duration) / 1000));
641
+ const delayMs = Math.max(1, Math.round(duration / steps));
642
+ // Simple easing path
643
+ const dx = x - from.x;
644
+ const dy = y - from.y;
645
+ for (let i = 1; i <= steps; i++) {
646
+ const t = i / steps;
647
+ const e = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
648
+ (0, index_js_1.mouseMove)(Math.round(from.x + dx * e), Math.round(from.y + dy * e));
649
+ await new Promise(r => setTimeout(r, delayMs));
650
+ }
651
+ // Click and verify
652
+ const result = clickAndVerify(x, y, {
653
+ button: options.button,
654
+ minChangePercent: options.minChangePercent,
655
+ timeoutMs: options.verifyTimeoutMs,
656
+ region: options.region,
657
+ });
658
+ return {
659
+ ...result,
660
+ finalPosition: { x, y },
661
+ };
662
+ }
663
+ /**
664
+ * Execute a batch of actions with async wrapper.
665
+ *
666
+ * Same as `executeBatch()` but returns a Promise, so it can be used
667
+ * in `Promise.all()` with other async operations.
668
+ */
669
+ async function executeBatchAsync(actions, options = {}) {
670
+ // Run the synchronous batch in a microtask to allow interleaving
671
+ return new Promise((resolve) => {
672
+ setImmediate(() => {
673
+ resolve(executeBatch(actions, options));
674
+ });
675
+ });
676
+ }
677
+ /**
678
+ * Convenience: smoothly move to position and click — async.
679
+ * The cursor is visible moving on screen the whole time.
680
+ */
681
+ async function smoothClickAt(x, y, options = {}) {
682
+ const from = (0, index_js_1.mouseGetPosition)();
683
+ const duration = options.duration ?? 350;
684
+ const steps = Math.max(2, Math.round((120 * duration) / 1000));
685
+ const delayMs = Math.max(1, Math.round(duration / steps));
686
+ const dx = x - from.x;
687
+ const dy = y - from.y;
688
+ for (let i = 1; i <= steps; i++) {
689
+ const t = i / steps;
690
+ const e = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
691
+ (0, index_js_1.mouseMove)(Math.round(from.x + dx * e), Math.round(from.y + dy * e));
692
+ if (i < steps)
693
+ await new Promise(r => setTimeout(r, delayMs));
694
+ }
695
+ (0, index_js_1.mouseClick)(options.button);
696
+ }
697
+ /**
698
+ * Convenience: smoothly move to a text field, click it, type text.
699
+ * Fully async and visually smooth.
700
+ */
701
+ async function smoothClickAndType(x, y, text, options = {}) {
702
+ await smoothClickAt(x, y, { duration: options.duration });
703
+ await new Promise(r => setTimeout(r, 50));
704
+ (0, index_js_1.keyboardType)(text, options.typeDelay);
705
+ }
706
+ /**
707
+ * Execute multiple action groups in TRUE parallel on native OS threads.
708
+ *
709
+ * Each group runs on its own Rust thread. Within a group, actions execute
710
+ * sequentially. Groups start simultaneously (or with optional start delays).
711
+ *
712
+ * This is the core primitive that makes Stelo faster than any other SDK —
713
+ * true OS-level parallelism, not async pretend.
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * // Move mouse AND type AND capture screen — all at the same time
718
+ * const result = agent.nativeParallel([
719
+ * {
720
+ * groupId: 'mouse',
721
+ * actions: [
722
+ * { type: 'mouseMoveSmooth', x: 500, y: 300, duration: 500 },
723
+ * { type: 'mouseClick' },
724
+ * ],
725
+ * },
726
+ * {
727
+ * groupId: 'keyboard',
728
+ * actions: [
729
+ * { type: 'delay', ms: 200 }, // Start typing 200ms after mouse starts
730
+ * { type: 'type', text: 'hello world' },
731
+ * ],
732
+ * },
733
+ * ]);
734
+ * console.log(result.totalDurationMs); // ~500ms, not ~700ms sequential
735
+ * ```
736
+ */
737
+ function nativeParallel(groups) {
738
+ const nativeResult = (0, index_js_1.parallelExecute)(groups);
739
+ return mapParallelResult(nativeResult);
740
+ }
741
+ /**
742
+ * Execute actions with interleaved timing — human-like overlapping input.
743
+ *
744
+ * Each action has a startAtMs offset. Actions with the same start time
745
+ * run in parallel on separate OS threads. This enables realistic
746
+ * overlapping mouse + keyboard behavior.
747
+ *
748
+ * @example
749
+ * ```typescript
750
+ * // Start moving mouse immediately, start typing while mouse still moving
751
+ * agent.interleave([
752
+ * { startAtMs: 0, type: 'mouseMoveSmooth', x: 500, y: 300, duration: 500 },
753
+ * { startAtMs: 150, type: 'type', text: 'hello' }, // starts while mouse moving
754
+ * { startAtMs: 500, type: 'mouseClick' }, // after mouse arrives
755
+ * ]);
756
+ * ```
757
+ */
758
+ function interleave(timedActions) {
759
+ const nativeResult = (0, index_js_1.interleavedExecute)(timedActions);
760
+ return mapParallelResult(nativeResult);
761
+ }
762
+ function mapParallelResult(nr) {
763
+ return {
764
+ groups: nr.groups.map((g) => ({
765
+ groupId: g.groupId,
766
+ results: g.results.map((r) => ({
767
+ index: r.index,
768
+ success: r.success,
769
+ error: r.error ?? undefined,
770
+ durationMs: r.durationMs,
771
+ mousePosition: r.mouseX != null && r.mouseY != null
772
+ ? { x: r.mouseX, y: r.mouseY }
773
+ : undefined,
774
+ changeDetected: r.changeDetected ?? undefined,
775
+ })),
776
+ durationMs: g.durationMs,
777
+ successCount: g.successCount,
778
+ failureCount: g.failureCount,
779
+ })),
780
+ totalDurationMs: nr.totalDurationMs,
781
+ totalActions: nr.totalActions,
782
+ totalSuccess: nr.totalSuccess,
783
+ totalFailures: nr.totalFailures,
784
+ allSucceeded: nr.allSucceeded,
785
+ };
786
+ }
787
+ /**
788
+ * Perform OCR on a screen region. Returns recognized text with positions.
789
+ *
790
+ * @example
791
+ * ```typescript
792
+ * // OCR the entire screen
793
+ * const result = agent.ocr();
794
+ * console.log(result.text);
795
+ *
796
+ * // OCR a specific region
797
+ * const result = agent.ocr({ x: 100, y: 200, width: 400, height: 50 });
798
+ * for (const word of result.lines[0]?.words ?? []) {
799
+ * console.log(`"${word.text}" at (${word.center.x}, ${word.center.y})`);
800
+ * }
801
+ * ```
802
+ */
803
+ function ocr(region) {
804
+ const raw = (0, index_js_1.ocrRecognize)(region?.x, region?.y, region?.width, region?.height);
805
+ return {
806
+ text: raw.text,
807
+ durationMs: raw.durationMs,
808
+ lines: raw.lines.map((line) => ({
809
+ text: line.text,
810
+ x: line.x,
811
+ y: line.y,
812
+ width: line.width,
813
+ height: line.height,
814
+ words: line.words.map((w) => ({
815
+ text: w.text,
816
+ x: w.x,
817
+ y: w.y,
818
+ width: w.width,
819
+ height: w.height,
820
+ confidence: w.confidence,
821
+ center: { x: w.x + w.width / 2, y: w.y + w.height / 2 },
822
+ })),
823
+ })),
824
+ };
825
+ }
826
+ /**
827
+ * Find text on screen via OCR and return its position.
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * const submit = agent.findText('Submit');
832
+ * if (submit) {
833
+ * mouse.clickAt(submit.center.x, submit.center.y);
834
+ * }
835
+ * ```
836
+ */
837
+ function findText(needle, region) {
838
+ const raw = (0, index_js_1.ocrFindText)(needle, region?.x, region?.y, region?.width, region?.height);
839
+ if (!raw)
840
+ return null;
841
+ return {
842
+ text: raw.text,
843
+ x: raw.x,
844
+ y: raw.y,
845
+ width: raw.width,
846
+ height: raw.height,
847
+ confidence: raw.confidence,
848
+ center: { x: raw.x + raw.width / 2, y: raw.y + raw.height / 2 },
849
+ };
850
+ }
851
+ /**
852
+ * Find text on screen and click its center. Game-changer for AI agents.
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * // Click the "Submit" button — no coordinates needed
857
+ * agent.clickText('Submit');
858
+ *
859
+ * // Click "Cancel" with right-click
860
+ * agent.clickText('Cancel', { button: 'right' });
861
+ * ```
862
+ *
863
+ * @throws Error if text not found on screen
864
+ */
865
+ function clickText(needle, options = {}) {
866
+ const pos = (0, index_js_1.ocrClickText)(needle, options.button, options.region?.x, options.region?.y, options.region?.width, options.region?.height);
867
+ return { x: pos.x, y: pos.y };
868
+ }
869
+ // ─────────────────────────────────────────────────────────────────────────────
870
+ // Smart Reactions — Wait for visual/text conditions before acting
871
+ // ─────────────────────────────────────────────────────────────────────────────
872
+ /**
873
+ * Wait until OCR detects the specified text on screen.
874
+ * Polls at a configurable interval. Returns the word position, or null on timeout.
875
+ *
876
+ * @example
877
+ * ```typescript
878
+ * // Wait up to 10s for "Loading complete" to appear
879
+ * const word = agent.waitForText('Loading complete', { timeout: 10000 });
880
+ * if (word) console.log('Found at', word.center);
881
+ * ```
882
+ */
883
+ function waitForText(needle, options = {}) {
884
+ const raw = (0, index_js_1.waitForText)(needle, options.timeout, options.interval, options.region?.x, options.region?.y, options.region?.width, options.region?.height);
885
+ if (!raw)
886
+ return null;
887
+ return {
888
+ text: raw.text,
889
+ x: raw.x,
890
+ y: raw.y,
891
+ width: raw.width,
892
+ height: raw.height,
893
+ confidence: raw.confidence,
894
+ center: { x: raw.x + raw.width / 2, y: raw.y + raw.height / 2 },
895
+ };
896
+ }
897
+ /**
898
+ * Wait for text to appear on screen, then click it.
899
+ * Combines waitForText + click in a single native call for lower latency.
900
+ *
901
+ * @example
902
+ * ```typescript
903
+ * // Wait for "Submit" button to appear, then click it
904
+ * const pos = agent.waitForTextAndClick('Submit', { timeout: 5000 });
905
+ * if (pos) console.log('Clicked at', pos);
906
+ * ```
907
+ */
908
+ function waitForTextAndClick(needle, options = {}) {
909
+ const raw = (0, index_js_1.waitForTextAndClick)(needle, options.timeout, options.interval, options.button, options.region?.x, options.region?.y, options.region?.width, options.region?.height);
910
+ return raw ? { x: raw.x, y: raw.y } : null;
911
+ }
912
+ /**
913
+ * Watch a screen region and wait for it to change.
914
+ * Returns the change percentage when threshold is exceeded, or null on timeout.
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ * // Watch a button area for any visual change
919
+ * const change = agent.watchRegion(
920
+ * { x: 200, y: 300, width: 100, height: 40 },
921
+ * { threshold: 2.0, timeout: 5000 }
922
+ * );
923
+ * if (change) console.log(`Region changed by ${change.toFixed(1)}%`);
924
+ * ```
925
+ */
926
+ function watchRegion(region, options = {}) {
927
+ return (0, index_js_1.watchRegionOnce)(region.x, region.y, region.width, region.height, options.threshold, options.timeout, options.interval);
928
+ }
929
+ /**
930
+ * Continuously watch a screen region and call a handler when it changes.
931
+ * Returns a stop function.
932
+ *
933
+ * @example
934
+ * ```typescript
935
+ * const stop = agent.onRegionChange(
936
+ * { x: 200, y: 300, width: 100, height: 40 },
937
+ * (changePct) => console.log(`Changed: ${changePct}%`),
938
+ * { threshold: 1.0, interval: 300 }
939
+ * );
940
+ * // Later...
941
+ * stop();
942
+ * ```
943
+ */
944
+ function onRegionChange(region, handler, options = {}) {
945
+ let running = true;
946
+ const interval = options.interval ?? 300;
947
+ const threshold = options.threshold ?? 1.0;
948
+ const poll = () => {
949
+ if (!running)
950
+ return;
951
+ const change = (0, index_js_1.watchRegionOnce)(region.x, region.y, region.width, region.height, threshold, interval + 100, // slight timeout buffer
952
+ interval);
953
+ if (change !== null && running) {
954
+ handler(change);
955
+ }
956
+ if (running) {
957
+ setTimeout(poll, 0);
958
+ }
959
+ };
960
+ setTimeout(poll, 0);
961
+ return () => { running = false; };
962
+ }
963
+ // ─────────────────────────────────────────────────────────────────────────────
964
+ // Hotkey System — Register global keyboard shortcuts
965
+ // ─────────────────────────────────────────────────────────────────────────────
966
+ /**
967
+ * Register a global hotkey handler. Starts listening for keyboard events
968
+ * and triggers the callback when the key combination is detected.
969
+ *
970
+ * @example
971
+ * ```typescript
972
+ * // Register Ctrl+Shift+A
973
+ * const unregister = agent.onHotkey('ctrl+shift+a', () => {
974
+ * console.log('Hotkey triggered!');
975
+ * });
976
+ *
977
+ * // Later: stop listening
978
+ * unregister();
979
+ * ```
980
+ */
981
+ function onHotkey(combo, handler, options = {}) {
982
+ // Parse combo: "ctrl+shift+a" → { ctrl: true, shift: true, alt: false, key: 'a' }
983
+ const parts = combo.toLowerCase().split('+').map(s => s.trim());
984
+ const modifiers = {
985
+ ctrl: parts.includes('ctrl') || parts.includes('control'),
986
+ shift: parts.includes('shift'),
987
+ alt: parts.includes('alt'),
988
+ meta: parts.includes('meta') || parts.includes('win') || parts.includes('cmd'),
989
+ };
990
+ const key = parts.find(p => !['ctrl', 'control', 'shift', 'alt', 'meta', 'win', 'cmd'].includes(p)) || '';
991
+ let running = true;
992
+ const pollMs = options.pollInterval ?? 50;
993
+ // Use hooks to poll for key events
994
+ const { startHooks, drainEvents, stopHooks } = require('../index.js');
995
+ startHooks({ captureKeyboard: true, captureMouseClicks: false, captureMouseMove: false, captureMouseWheel: false, bufferSize: 64 });
996
+ const held = new Set();
997
+ const poll = () => {
998
+ if (!running)
999
+ return;
1000
+ try {
1001
+ const events = drainEvents();
1002
+ for (const ev of events) {
1003
+ if (ev.type === 'keydown' || ev.type === 'KeyDown') {
1004
+ held.add((ev.keyName || '').toLowerCase());
1005
+ }
1006
+ else if (ev.type === 'keyup' || ev.type === 'KeyUp') {
1007
+ held.delete((ev.keyName || '').toLowerCase());
1008
+ }
1009
+ // Check if combo matches on keydown
1010
+ if (ev.type === 'keydown' || ev.type === 'KeyDown') {
1011
+ const keyMatch = key === '' || (ev.keyName || '').toLowerCase() === key;
1012
+ const ctrlMatch = !modifiers.ctrl || held.has('lcontrol') || held.has('rcontrol') || held.has('control');
1013
+ const shiftMatch = !modifiers.shift || held.has('lshift') || held.has('rshift') || held.has('shift');
1014
+ const altMatch = !modifiers.alt || held.has('lalt') || held.has('ralt') || held.has('alt') || held.has('lmenu') || held.has('rmenu');
1015
+ if (keyMatch && ctrlMatch && shiftMatch && altMatch) {
1016
+ handler();
1017
+ }
1018
+ }
1019
+ }
1020
+ }
1021
+ catch { /* ignore errors during polling */ }
1022
+ if (running)
1023
+ setTimeout(poll, pollMs);
1024
+ };
1025
+ setTimeout(poll, 0);
1026
+ return () => {
1027
+ running = false;
1028
+ try {
1029
+ stopHooks();
1030
+ }
1031
+ catch { /* ignore */ }
1032
+ };
1033
+ }
1034
+ /**
1035
+ * Wait for a hotkey combo to be pressed. Returns a promise that resolves
1036
+ * when the combo is detected, or rejects on timeout.
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * await agent.waitForHotkey('ctrl+shift+s', { timeout: 30000 });
1041
+ * console.log('User pressed Ctrl+Shift+S!');
1042
+ * ```
1043
+ */
1044
+ function waitForHotkey(combo, options = {}) {
1045
+ const timeout = options.timeout ?? 30000;
1046
+ return new Promise((resolve, reject) => {
1047
+ const timer = setTimeout(() => {
1048
+ unregister();
1049
+ reject(new Error(`Hotkey '${combo}' not pressed within ${timeout}ms`));
1050
+ }, timeout);
1051
+ const unregister = onHotkey(combo, () => {
1052
+ clearTimeout(timer);
1053
+ unregister();
1054
+ resolve();
1055
+ });
1056
+ });
1057
+ }
1058
+ // ─────────────────────────────────────────────────────────────────────────────
1059
+ // Default Export
1060
+ // ─────────────────────────────────────────────────────────────────────────────
1061
+ exports.agent = {
1062
+ // Core
1063
+ executeBatch,
1064
+ executeBatchAsync,
1065
+ clickAndVerify,
1066
+ hotkeyAndVerify,
1067
+ // Async / Non-blocking
1068
+ parallel,
1069
+ moveClickVerify,
1070
+ smoothClickAt,
1071
+ smoothClickAndType,
1072
+ // Streaming control
1073
+ createCursorStream,
1074
+ // Relative movement
1075
+ moveRelative,
1076
+ moveRelativeSmooth,
1077
+ // Text input
1078
+ typeAndWaitStable,
1079
+ // Gesture
1080
+ recordMouseTrail,
1081
+ replayMouseTrail,
1082
+ // Recovery
1083
+ releaseAllModifiers,
1084
+ // Fluent API
1085
+ sequence,
1086
+ ActionSequence,
1087
+ // Convenience
1088
+ clickAndWait,
1089
+ typeAndEnter,
1090
+ // Native Parallel Pipeline (true OS-thread parallelism)
1091
+ nativeParallel,
1092
+ interleave,
1093
+ // OCR (native text recognition)
1094
+ ocr,
1095
+ findText,
1096
+ clickText,
1097
+ // Smart Reactions
1098
+ waitForText,
1099
+ waitForTextAndClick,
1100
+ watchRegion,
1101
+ onRegionChange,
1102
+ // Hotkey System
1103
+ onHotkey,
1104
+ waitForHotkey,
1105
+ };
1106
+ exports.default = exports.agent;
1107
+ //# sourceMappingURL=agent.js.map