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.
- package/LICENSE +184 -0
- package/README.md +853 -0
- package/dist/accessibility.d.ts +227 -0
- package/dist/accessibility.d.ts.map +1 -0
- package/dist/accessibility.js +602 -0
- package/dist/accessibility.js.map +1 -0
- package/dist/agent.d.ts +870 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +1107 -0
- package/dist/agent.js.map +1 -0
- package/dist/audio-stream.d.ts +114 -0
- package/dist/audio-stream.d.ts.map +1 -0
- package/dist/audio-stream.js +167 -0
- package/dist/audio-stream.js.map +1 -0
- package/dist/clipboard.d.ts +99 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +352 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/config.d.ts +183 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +477 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +213 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +387 -0
- package/dist/context.js.map +1 -0
- package/dist/cortex.d.ts +548 -0
- package/dist/cortex.d.ts.map +1 -0
- package/dist/cortex.js +1479 -0
- package/dist/cortex.js.map +1 -0
- package/dist/errors.d.ts +133 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +278 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +227 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +429 -0
- package/dist/events.js.map +1 -0
- package/dist/executor.d.ts +212 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +545 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.d.ts +159 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +533 -0
- package/dist/integration.js.map +1 -0
- package/dist/keyboard.d.ts +276 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +404 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/logger.d.ts +198 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +516 -0
- package/dist/logger.js.map +1 -0
- package/dist/middleware.d.ts +183 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +493 -0
- package/dist/middleware.js.map +1 -0
- package/dist/monitor.d.ts +136 -0
- package/dist/monitor.d.ts.map +1 -0
- package/dist/monitor.js +341 -0
- package/dist/monitor.js.map +1 -0
- package/dist/mouse.d.ts +290 -0
- package/dist/mouse.d.ts.map +1 -0
- package/dist/mouse.js +466 -0
- package/dist/mouse.js.map +1 -0
- package/dist/plugin.d.ts +157 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +409 -0
- package/dist/plugin.js.map +1 -0
- package/dist/process.d.ts +106 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +326 -0
- package/dist/process.js.map +1 -0
- package/dist/recorder.d.ts +100 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +258 -0
- package/dist/recorder.js.map +1 -0
- package/dist/safety.d.ts +59 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +98 -0
- package/dist/safety.js.map +1 -0
- package/dist/scheduler.d.ts +152 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +615 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/screen.d.ts +96 -0
- package/dist/screen.d.ts.map +1 -0
- package/dist/screen.js +154 -0
- package/dist/screen.js.map +1 -0
- package/dist/session.d.ts +209 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +479 -0
- package/dist/session.js.map +1 -0
- package/dist/stream.d.ts +168 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +298 -0
- package/dist/stream.js.map +1 -0
- package/dist/telemetry.d.ts +223 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +433 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +165 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/bezier.d.ts +51 -0
- package/dist/utils/bezier.d.ts.map +1 -0
- package/dist/utils/bezier.js +117 -0
- package/dist/utils/bezier.js.map +1 -0
- package/dist/utils/helpers.d.ts +90 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +143 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validation.d.ts +254 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +478 -0
- package/dist/validation.js.map +1 -0
- package/dist/vision.d.ts +719 -0
- package/dist/vision.d.ts.map +1 -0
- package/dist/vision.js +1197 -0
- package/dist/vision.js.map +1 -0
- package/dist/window.d.ts +80 -0
- package/dist/window.d.ts.map +1 -0
- package/dist/window.js +170 -0
- package/dist/window.js.map +1 -0
- package/dist/workflow.d.ts +224 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +578 -0
- package/dist/workflow.js.map +1 -0
- package/index.d.ts +840 -0
- package/index.js +495 -0
- package/package.json +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bezier.d.ts","sourceRoot":"","sources":["../../ts/utils/bezier.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM;IACjB;;OAEG;cAEG,WAAW,MACX,WAAW,MACX,WAAW,MACX,WAAW,KACZ,MAAM,GACR,WAAW;IAYd;;OAEG;kBAEG,WAAW,MACX,WAAW,MACX,WAAW,KACZ,MAAM,GACR,WAAW;IAQd;;OAEG;oBAEG,WAAW,MACX,WAAW,MACX,WAAW,MACX,WAAW,YACL,kBAAkB,GAC3B,WAAW,EAAE;IAShB;;OAEG;kBAEG,WAAW,MACX,WAAW,MACX,WAAW,MACX,WAAW,qBAEd,MAAM;IAaT;;;OAGG;+BAEM,WAAW,OACb,WAAW,oBAEf;QAAE,EAAE,EAAE,WAAW,CAAC;QAAC,EAAE,EAAE,WAAW,CAAA;KAAE;IAkBvC;;;OAGG;kBACW,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM,GAAG,MAAM;IAgB5E,iCAAiC;cACvB,MAAM,GAAG,MAAM;IAIzB,kCAAkC;eACvB,MAAM,GAAG,MAAM;IAI1B,qCAAqC;iBACxB,MAAM,GAAG,MAAM;CAG7B,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Stelo — Bezier Curve Utilities (TypeScript)
|
|
4
|
+
// ============================================================================
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.bezier = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Pure-TypeScript bezier curve utilities for path planning, easing, and
|
|
9
|
+
* visualization. These complement the native Rust bezier implementation
|
|
10
|
+
* used for actual mouse movement.
|
|
11
|
+
*/
|
|
12
|
+
exports.bezier = {
|
|
13
|
+
/**
|
|
14
|
+
* Evaluate a cubic bezier curve at parameter t ∈ [0, 1].
|
|
15
|
+
*/
|
|
16
|
+
cubic(p0, p1, p2, p3, t) {
|
|
17
|
+
const u = 1 - t;
|
|
18
|
+
const uu = u * u;
|
|
19
|
+
const uuu = uu * u;
|
|
20
|
+
const tt = t * t;
|
|
21
|
+
const ttt = tt * t;
|
|
22
|
+
return {
|
|
23
|
+
x: uuu * p0.x + 3 * uu * t * p1.x + 3 * u * tt * p2.x + ttt * p3.x,
|
|
24
|
+
y: uuu * p0.y + 3 * uu * t * p1.y + 3 * u * tt * p2.y + ttt * p3.y,
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Evaluate a quadratic bezier curve at parameter t ∈ [0, 1].
|
|
29
|
+
*/
|
|
30
|
+
quadratic(p0, p1, p2, t) {
|
|
31
|
+
const u = 1 - t;
|
|
32
|
+
return {
|
|
33
|
+
x: u * u * p0.x + 2 * u * t * p1.x + t * t * p2.x,
|
|
34
|
+
y: u * u * p0.y + 2 * u * t * p1.y + t * t * p2.y,
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Sample a cubic bezier curve and return an array of evenly-spaced points.
|
|
39
|
+
*/
|
|
40
|
+
sampleCubic(p0, p1, p2, p3, options) {
|
|
41
|
+
const steps = options?.steps ?? 100;
|
|
42
|
+
const points = [];
|
|
43
|
+
for (let i = 0; i <= steps; i++) {
|
|
44
|
+
points.push(exports.bezier.cubic(p0, p1, p2, p3, i / steps));
|
|
45
|
+
}
|
|
46
|
+
return points;
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Compute the approximate arc length of a cubic bezier by summing segment distances.
|
|
50
|
+
*/
|
|
51
|
+
arcLength(p0, p1, p2, p3, samples = 500) {
|
|
52
|
+
let length = 0;
|
|
53
|
+
let prev = p0;
|
|
54
|
+
for (let i = 1; i <= samples; i++) {
|
|
55
|
+
const pt = exports.bezier.cubic(p0, p1, p2, p3, i / samples);
|
|
56
|
+
const dx = pt.x - prev.x;
|
|
57
|
+
const dy = pt.y - prev.y;
|
|
58
|
+
length += Math.sqrt(dx * dx + dy * dy);
|
|
59
|
+
prev = pt;
|
|
60
|
+
}
|
|
61
|
+
return length;
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* Generate random control points for a cubic bezier between two endpoints.
|
|
65
|
+
* Useful for creating natural-looking mouse movement curves.
|
|
66
|
+
*/
|
|
67
|
+
randomControlPoints(start, end, spread = 0.4) {
|
|
68
|
+
const dx = end.x - start.x;
|
|
69
|
+
const dy = end.y - start.y;
|
|
70
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
71
|
+
const offset = dist * spread;
|
|
72
|
+
return {
|
|
73
|
+
p1: {
|
|
74
|
+
x: start.x + dx * 0.25 + (Math.random() - 0.5) * offset,
|
|
75
|
+
y: start.y + dy * 0.25 + (Math.random() - 0.5) * offset,
|
|
76
|
+
},
|
|
77
|
+
p2: {
|
|
78
|
+
x: start.x + dx * 0.75 + (Math.random() - 0.5) * offset,
|
|
79
|
+
y: start.y + dy * 0.75 + (Math.random() - 0.5) * offset,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Standard CSS-style cubic-bezier easing function.
|
|
85
|
+
* Returns y for a given x ∈ [0, 1] using Newton's method.
|
|
86
|
+
*/
|
|
87
|
+
cssEasing(x1, y1, x2, y2, t) {
|
|
88
|
+
// Newton-Raphson to find parameter for x
|
|
89
|
+
let guess = t;
|
|
90
|
+
for (let i = 0; i < 8; i++) {
|
|
91
|
+
const x = exports.bezier.cubic({ x: 0, y: 0 }, { x: x1, y: y1 }, { x: x2, y: y2 }, { x: 1, y: 1 }, guess).x;
|
|
92
|
+
const dx = x - t;
|
|
93
|
+
if (Math.abs(dx) < 1e-7)
|
|
94
|
+
break;
|
|
95
|
+
// derivative
|
|
96
|
+
const u = 1 - guess;
|
|
97
|
+
const dxdt = 3 * u * u * x1 + 6 * u * guess * (x2 - x1) + 3 * guess * guess * (1 - x2);
|
|
98
|
+
if (Math.abs(dxdt) < 1e-7)
|
|
99
|
+
break;
|
|
100
|
+
guess -= dx / dxdt;
|
|
101
|
+
}
|
|
102
|
+
return exports.bezier.cubic({ x: 0, y: 0 }, { x: x1, y: y1 }, { x: x2, y: y2 }, { x: 1, y: 1 }, guess).y;
|
|
103
|
+
},
|
|
104
|
+
/** Predefined easing: ease-in */
|
|
105
|
+
easeIn(t) {
|
|
106
|
+
return exports.bezier.cssEasing(0.42, 0, 1, 1, t);
|
|
107
|
+
},
|
|
108
|
+
/** Predefined easing: ease-out */
|
|
109
|
+
easeOut(t) {
|
|
110
|
+
return exports.bezier.cssEasing(0, 0, 0.58, 1, t);
|
|
111
|
+
},
|
|
112
|
+
/** Predefined easing: ease-in-out */
|
|
113
|
+
easeInOut(t) {
|
|
114
|
+
return exports.bezier.cssEasing(0.42, 0, 0.58, 1, t);
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=bezier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bezier.js","sourceRoot":"","sources":["../../ts/utils/bezier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause execution for a specified number of milliseconds.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { delay } from 'stelo';
|
|
7
|
+
* await delay(500); // wait half a second
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare function delay(ms: number): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Retry an async operation up to `maxAttempts` times with optional backoff.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { retry, screen } from 'stelo';
|
|
17
|
+
* const color = await retry(() => {
|
|
18
|
+
* const c = screen.getPixelColor(100, 200);
|
|
19
|
+
* if (c.hex === '#FF0000') return c;
|
|
20
|
+
* throw new Error('Color not found');
|
|
21
|
+
* }, { maxAttempts: 10, delayMs: 200 });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function retry<T>(fn: () => T | Promise<T>, options?: {
|
|
25
|
+
/** Maximum number of attempts (default: 3) */
|
|
26
|
+
maxAttempts?: number;
|
|
27
|
+
/** Delay between retries in ms (default: 100) */
|
|
28
|
+
delayMs?: number;
|
|
29
|
+
/** Multiply delay by this factor each retry (default: 1.0 = no backoff) */
|
|
30
|
+
backoffMultiplier?: number;
|
|
31
|
+
}): Promise<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Wait until a predicate returns `true`, polling at a fixed interval.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { waitUntil, screen } from 'stelo';
|
|
38
|
+
* await waitUntil(() => screen.getPixelColor(100, 200).hex === '#00FF00', {
|
|
39
|
+
* timeoutMs: 5000,
|
|
40
|
+
* intervalMs: 100,
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function waitUntil(predicate: () => boolean | Promise<boolean>, options?: {
|
|
45
|
+
/** Maximum time to wait in ms (default: 10000) */
|
|
46
|
+
timeoutMs?: number;
|
|
47
|
+
/** Polling interval in ms (default: 100) */
|
|
48
|
+
intervalMs?: number;
|
|
49
|
+
/** Error message on timeout */
|
|
50
|
+
message?: string;
|
|
51
|
+
}): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Run multiple async operations in parallel with optional concurrency limit.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { batch, mouse } from 'stelo';
|
|
58
|
+
* // Click four positions concurrency=2
|
|
59
|
+
* await batch(
|
|
60
|
+
* [
|
|
61
|
+
* () => mouse.moveAndClick(100, 100),
|
|
62
|
+
* () => mouse.moveAndClick(200, 200),
|
|
63
|
+
* () => mouse.moveAndClick(300, 300),
|
|
64
|
+
* () => mouse.moveAndClick(400, 400),
|
|
65
|
+
* ],
|
|
66
|
+
* { concurrency: 2 },
|
|
67
|
+
* );
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function batch<T>(tasks: Array<() => Promise<T>>, options?: {
|
|
71
|
+
/** Max simultaneous tasks. 0 = unlimited (default: 0) */
|
|
72
|
+
concurrency?: number;
|
|
73
|
+
}): Promise<T[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Clamp a number between a minimum and maximum value.
|
|
76
|
+
*/
|
|
77
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
78
|
+
/**
|
|
79
|
+
* Linear interpolation between two values.
|
|
80
|
+
*/
|
|
81
|
+
export declare function lerp(a: number, b: number, t: number): number;
|
|
82
|
+
/**
|
|
83
|
+
* Generate a random integer between min (inclusive) and max (inclusive).
|
|
84
|
+
*/
|
|
85
|
+
export declare function randomInt(min: number, max: number): number;
|
|
86
|
+
/**
|
|
87
|
+
* Generate a random float between min and max.
|
|
88
|
+
*/
|
|
89
|
+
export declare function randomFloat(min: number, max: number): number;
|
|
90
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../ts/utils/helpers.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,OAAO,CAAC,EAAE;IACR,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GACA,OAAO,CAAC,CAAC,CAAC,CAqBZ;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAC3C,OAAO,CAAC,EAAE;IACR,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE;IACR,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACA,OAAO,CAAC,CAAC,EAAE,CAAC,CAsBd;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Stelo — General-Purpose Helper Utilities
|
|
4
|
+
// ============================================================================
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.delay = delay;
|
|
7
|
+
exports.retry = retry;
|
|
8
|
+
exports.waitUntil = waitUntil;
|
|
9
|
+
exports.batch = batch;
|
|
10
|
+
exports.clamp = clamp;
|
|
11
|
+
exports.lerp = lerp;
|
|
12
|
+
exports.randomInt = randomInt;
|
|
13
|
+
exports.randomFloat = randomFloat;
|
|
14
|
+
/**
|
|
15
|
+
* Pause execution for a specified number of milliseconds.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { delay } from 'stelo';
|
|
20
|
+
* await delay(500); // wait half a second
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function delay(ms) {
|
|
24
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Retry an async operation up to `maxAttempts` times with optional backoff.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { retry, screen } from 'stelo';
|
|
32
|
+
* const color = await retry(() => {
|
|
33
|
+
* const c = screen.getPixelColor(100, 200);
|
|
34
|
+
* if (c.hex === '#FF0000') return c;
|
|
35
|
+
* throw new Error('Color not found');
|
|
36
|
+
* }, { maxAttempts: 10, delayMs: 200 });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
async function retry(fn, options) {
|
|
40
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
41
|
+
const baseDelay = options?.delayMs ?? 100;
|
|
42
|
+
const backoff = options?.backoffMultiplier ?? 1.0;
|
|
43
|
+
let lastError;
|
|
44
|
+
let currentDelay = baseDelay;
|
|
45
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
46
|
+
try {
|
|
47
|
+
return await fn();
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
51
|
+
if (attempt < maxAttempts) {
|
|
52
|
+
await delay(currentDelay);
|
|
53
|
+
currentDelay = Math.round(currentDelay * backoff);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
throw lastError ?? new Error(`retry: all ${maxAttempts} attempts failed`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Wait until a predicate returns `true`, polling at a fixed interval.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { waitUntil, screen } from 'stelo';
|
|
65
|
+
* await waitUntil(() => screen.getPixelColor(100, 200).hex === '#00FF00', {
|
|
66
|
+
* timeoutMs: 5000,
|
|
67
|
+
* intervalMs: 100,
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
async function waitUntil(predicate, options) {
|
|
72
|
+
const timeout = options?.timeoutMs ?? 10_000;
|
|
73
|
+
const interval = options?.intervalMs ?? 100;
|
|
74
|
+
const start = Date.now();
|
|
75
|
+
while (true) {
|
|
76
|
+
if (await predicate())
|
|
77
|
+
return;
|
|
78
|
+
if (Date.now() - start >= timeout) {
|
|
79
|
+
throw new Error(options?.message ?? `waitUntil: timed out after ${timeout}ms`);
|
|
80
|
+
}
|
|
81
|
+
await delay(interval);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Run multiple async operations in parallel with optional concurrency limit.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* import { batch, mouse } from 'stelo';
|
|
90
|
+
* // Click four positions concurrency=2
|
|
91
|
+
* await batch(
|
|
92
|
+
* [
|
|
93
|
+
* () => mouse.moveAndClick(100, 100),
|
|
94
|
+
* () => mouse.moveAndClick(200, 200),
|
|
95
|
+
* () => mouse.moveAndClick(300, 300),
|
|
96
|
+
* () => mouse.moveAndClick(400, 400),
|
|
97
|
+
* ],
|
|
98
|
+
* { concurrency: 2 },
|
|
99
|
+
* );
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
async function batch(tasks, options) {
|
|
103
|
+
const limit = options?.concurrency ?? 0;
|
|
104
|
+
if (limit <= 0 || limit >= tasks.length) {
|
|
105
|
+
return Promise.all(tasks.map((t) => t()));
|
|
106
|
+
}
|
|
107
|
+
const results = new Array(tasks.length);
|
|
108
|
+
let nextIndex = 0;
|
|
109
|
+
async function worker() {
|
|
110
|
+
while (nextIndex < tasks.length) {
|
|
111
|
+
const idx = nextIndex++;
|
|
112
|
+
results[idx] = await tasks[idx]();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const workers = Array.from({ length: Math.min(limit, tasks.length) }, () => worker());
|
|
116
|
+
await Promise.all(workers);
|
|
117
|
+
return results;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Clamp a number between a minimum and maximum value.
|
|
121
|
+
*/
|
|
122
|
+
function clamp(value, min, max) {
|
|
123
|
+
return Math.min(Math.max(value, min), max);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Linear interpolation between two values.
|
|
127
|
+
*/
|
|
128
|
+
function lerp(a, b, t) {
|
|
129
|
+
return a + (b - a) * t;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Generate a random integer between min (inclusive) and max (inclusive).
|
|
133
|
+
*/
|
|
134
|
+
function randomInt(min, max) {
|
|
135
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generate a random float between min and max.
|
|
139
|
+
*/
|
|
140
|
+
function randomFloat(min, max) {
|
|
141
|
+
return Math.random() * (max - min) + min;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../ts/utils/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,EACT,WAAW,GACZ,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Stelo — TypeScript Utilities Barrel Export
|
|
4
|
+
// ============================================================================
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.randomFloat = exports.randomInt = exports.lerp = exports.clamp = exports.batch = exports.waitUntil = exports.retry = exports.delay = exports.bezier = void 0;
|
|
7
|
+
var bezier_1 = require("./bezier");
|
|
8
|
+
Object.defineProperty(exports, "bezier", { enumerable: true, get: function () { return bezier_1.bezier; } });
|
|
9
|
+
var helpers_1 = require("./helpers");
|
|
10
|
+
Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return helpers_1.delay; } });
|
|
11
|
+
Object.defineProperty(exports, "retry", { enumerable: true, get: function () { return helpers_1.retry; } });
|
|
12
|
+
Object.defineProperty(exports, "waitUntil", { enumerable: true, get: function () { return helpers_1.waitUntil; } });
|
|
13
|
+
Object.defineProperty(exports, "batch", { enumerable: true, get: function () { return helpers_1.batch; } });
|
|
14
|
+
Object.defineProperty(exports, "clamp", { enumerable: true, get: function () { return helpers_1.clamp; } });
|
|
15
|
+
Object.defineProperty(exports, "lerp", { enumerable: true, get: function () { return helpers_1.lerp; } });
|
|
16
|
+
Object.defineProperty(exports, "randomInt", { enumerable: true, get: function () { return helpers_1.randomInt; } });
|
|
17
|
+
Object.defineProperty(exports, "randomFloat", { enumerable: true, get: function () { return helpers_1.randomFloat; } });
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../ts/utils/index.ts"],"names":[],"mappings":";AAAA,+EAA+E;AAC/E,6CAA6C;AAC7C,+EAA+E;;;AAE/E,mCAAkC;AAAzB,gGAAA,MAAM,OAAA;AAEf,qCASmB;AARjB,gGAAA,KAAK,OAAA;AACL,gGAAA,KAAK,OAAA;AACL,oGAAA,SAAS,OAAA;AACT,gGAAA,KAAK,OAAA;AACL,gGAAA,KAAK,OAAA;AACL,+FAAA,IAAI,OAAA;AACJ,oGAAA,SAAS,OAAA;AACT,sGAAA,WAAW,OAAA"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import type { Point, Region, ScreenSize } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Validation error with details
|
|
4
|
+
*/
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
readonly field: string;
|
|
8
|
+
readonly value: unknown;
|
|
9
|
+
readonly constraint: string;
|
|
10
|
+
constructor(field: string, value: unknown, constraint: string, code?: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result type for operations that can fail
|
|
14
|
+
*/
|
|
15
|
+
export type Result<T, E = Error> = {
|
|
16
|
+
ok: true;
|
|
17
|
+
value: T;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
error: E;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Create a successful result
|
|
24
|
+
*/
|
|
25
|
+
export declare function ok<T>(value: T): Result<T, never>;
|
|
26
|
+
/**
|
|
27
|
+
* Create a failed result
|
|
28
|
+
*/
|
|
29
|
+
export declare function err<E>(error: E): Result<never, E>;
|
|
30
|
+
/**
|
|
31
|
+
* Unwrap a result, throwing if it's an error
|
|
32
|
+
*/
|
|
33
|
+
export declare function unwrap<T>(result: Result<T>): T;
|
|
34
|
+
/**
|
|
35
|
+
* Validate that a value is a finite number
|
|
36
|
+
* @throws ValidationError if validation fails
|
|
37
|
+
*/
|
|
38
|
+
declare function validateNumber(value: unknown, field: string): asserts value is number;
|
|
39
|
+
/**
|
|
40
|
+
* Validate that a value is an integer
|
|
41
|
+
* @throws ValidationError if validation fails
|
|
42
|
+
*/
|
|
43
|
+
declare function validateInteger(value: unknown, field: string): asserts value is number;
|
|
44
|
+
/**
|
|
45
|
+
* Validate that a value is a positive integer
|
|
46
|
+
* @throws ValidationError if validation fails
|
|
47
|
+
*/
|
|
48
|
+
declare function validatePositiveInteger(value: unknown, field: string): asserts value is number;
|
|
49
|
+
/**
|
|
50
|
+
* Validate a coordinate value (integer, reasonable range)
|
|
51
|
+
* @throws ValidationError if validation fails
|
|
52
|
+
*/
|
|
53
|
+
declare function validateCoordinate(value: unknown, field: string): asserts value is number;
|
|
54
|
+
/**
|
|
55
|
+
* Validate that coordinates are within screen bounds
|
|
56
|
+
* @throws ValidationError if validation fails
|
|
57
|
+
*/
|
|
58
|
+
declare function validateInBounds(point: {
|
|
59
|
+
x: unknown;
|
|
60
|
+
y: unknown;
|
|
61
|
+
}, screenSize: ScreenSize, field?: string): asserts point is Point;
|
|
62
|
+
/**
|
|
63
|
+
* Validate a region has valid dimensions
|
|
64
|
+
* @throws ValidationError if validation fails
|
|
65
|
+
*/
|
|
66
|
+
declare function validateRegion(region: unknown, field?: string): asserts region is Region;
|
|
67
|
+
/**
|
|
68
|
+
* Validate a string is non-empty
|
|
69
|
+
* @throws ValidationError if validation fails
|
|
70
|
+
*/
|
|
71
|
+
declare function validateNonEmptyString(value: unknown, field: string): asserts value is string;
|
|
72
|
+
/**
|
|
73
|
+
* Validate a string has max length
|
|
74
|
+
* @throws ValidationError if validation fails
|
|
75
|
+
*/
|
|
76
|
+
declare function validateMaxLength(value: string, maxLen: number, field: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Validate duration in milliseconds
|
|
79
|
+
* @throws ValidationError if validation fails
|
|
80
|
+
*/
|
|
81
|
+
declare function validateDuration(value: unknown, field: string, maxMs?: number): asserts value is number;
|
|
82
|
+
/**
|
|
83
|
+
* Validate a value is within a range
|
|
84
|
+
* @throws ValidationError if validation fails
|
|
85
|
+
*/
|
|
86
|
+
declare function validateRange(value: number, min: number, max: number, field: string): void;
|
|
87
|
+
/**
|
|
88
|
+
* Validate a key name is valid
|
|
89
|
+
* @throws ValidationError if validation fails
|
|
90
|
+
*/
|
|
91
|
+
declare function validateKeyName(value: unknown, field: string): asserts value is string;
|
|
92
|
+
declare function safeCoordinate(value: unknown, field: string): Result<number, ValidationError>;
|
|
93
|
+
declare function safeInBounds(point: {
|
|
94
|
+
x: unknown;
|
|
95
|
+
y: unknown;
|
|
96
|
+
}, screenSize: ScreenSize, field?: string): Result<Point, ValidationError>;
|
|
97
|
+
declare function safeRegion(region: unknown, field?: string): Result<Region, ValidationError>;
|
|
98
|
+
declare function safeNumber(value: unknown, field: string): Result<number, ValidationError>;
|
|
99
|
+
/**
|
|
100
|
+
* Validation utilities for enterprise-grade input checking
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import { validate } from 'stelo';
|
|
105
|
+
*
|
|
106
|
+
* // Validate coordinates
|
|
107
|
+
* validate.coordinate(x, 'x');
|
|
108
|
+
* validate.coordinate(y, 'y');
|
|
109
|
+
*
|
|
110
|
+
* // Validate within screen bounds
|
|
111
|
+
* validate.inBounds({ x, y }, screenSize);
|
|
112
|
+
*
|
|
113
|
+
* // Validate region
|
|
114
|
+
* validate.region(region);
|
|
115
|
+
*
|
|
116
|
+
* // Safe validation (returns Result)
|
|
117
|
+
* const result = validate.safe.coordinate(x, 'x');
|
|
118
|
+
* if (!result.ok) console.error(result.error);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export declare const validate: {
|
|
122
|
+
number: typeof validateNumber;
|
|
123
|
+
integer: typeof validateInteger;
|
|
124
|
+
positiveInteger: typeof validatePositiveInteger;
|
|
125
|
+
coordinate: typeof validateCoordinate;
|
|
126
|
+
inBounds: typeof validateInBounds;
|
|
127
|
+
region: typeof validateRegion;
|
|
128
|
+
nonEmptyString: typeof validateNonEmptyString;
|
|
129
|
+
maxLength: typeof validateMaxLength;
|
|
130
|
+
duration: typeof validateDuration;
|
|
131
|
+
range: typeof validateRange;
|
|
132
|
+
keyName: typeof validateKeyName;
|
|
133
|
+
safe: {
|
|
134
|
+
coordinate: typeof safeCoordinate;
|
|
135
|
+
inBounds: typeof safeInBounds;
|
|
136
|
+
region: typeof safeRegion;
|
|
137
|
+
number: typeof safeNumber;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Audit log entry
|
|
142
|
+
*/
|
|
143
|
+
export interface AuditLogEntry {
|
|
144
|
+
timestamp: string;
|
|
145
|
+
operation: string;
|
|
146
|
+
args: Record<string, unknown>;
|
|
147
|
+
success: boolean;
|
|
148
|
+
error?: string;
|
|
149
|
+
durationMs: number;
|
|
150
|
+
}
|
|
151
|
+
type AuditHandler = (entry: AuditLogEntry) => void;
|
|
152
|
+
/**
|
|
153
|
+
* Security utilities for enterprise deployments
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* import { security } from 'stelo';
|
|
158
|
+
*
|
|
159
|
+
* // Enable audit logging
|
|
160
|
+
* security.enableAudit();
|
|
161
|
+
*
|
|
162
|
+
* // Subscribe to audit events
|
|
163
|
+
* security.onAudit((entry) => {
|
|
164
|
+
* console.log(`[AUDIT] ${entry.operation}: ${entry.success}`);
|
|
165
|
+
* });
|
|
166
|
+
*
|
|
167
|
+
* // Get audit log
|
|
168
|
+
* const log = security.getAuditLog();
|
|
169
|
+
*
|
|
170
|
+
* // Sanitize text for typing (remove control characters)
|
|
171
|
+
* const safeText = security.sanitizeText(userInput);
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export declare const security: {
|
|
175
|
+
/**
|
|
176
|
+
* Enable audit logging
|
|
177
|
+
*/
|
|
178
|
+
enableAudit(maxEntries?: number): void;
|
|
179
|
+
/**
|
|
180
|
+
* Disable audit logging
|
|
181
|
+
*/
|
|
182
|
+
disableAudit(): void;
|
|
183
|
+
/**
|
|
184
|
+
* Check if audit logging is enabled
|
|
185
|
+
*/
|
|
186
|
+
isAuditEnabled(): boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Subscribe to audit events
|
|
189
|
+
*/
|
|
190
|
+
onAudit(handler: AuditHandler): () => void;
|
|
191
|
+
/**
|
|
192
|
+
* Log an audit entry
|
|
193
|
+
* @internal Used by Stelo internals
|
|
194
|
+
*/
|
|
195
|
+
logAudit(operation: string, args: Record<string, unknown>, success: boolean, durationMs: number, error?: string): void;
|
|
196
|
+
/**
|
|
197
|
+
* Get the audit log
|
|
198
|
+
*/
|
|
199
|
+
getAuditLog(limit?: number): AuditLogEntry[];
|
|
200
|
+
/**
|
|
201
|
+
* Clear the audit log
|
|
202
|
+
*/
|
|
203
|
+
clearAuditLog(): void;
|
|
204
|
+
/**
|
|
205
|
+
* Sanitize text for safe typing (remove control characters)
|
|
206
|
+
*/
|
|
207
|
+
sanitizeText(text: string): string;
|
|
208
|
+
/**
|
|
209
|
+
* Redact potentially sensitive values from an object
|
|
210
|
+
*/
|
|
211
|
+
redactSensitive(obj: Record<string, unknown>): Record<string, unknown>;
|
|
212
|
+
/**
|
|
213
|
+
* Check if running in a sandboxed environment (best effort detection)
|
|
214
|
+
*/
|
|
215
|
+
detectSandbox(): {
|
|
216
|
+
sandboxed: boolean;
|
|
217
|
+
indicators: string[];
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Generate a secure operation ID
|
|
221
|
+
*/
|
|
222
|
+
generateOperationId(): string;
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Token bucket rate limiter
|
|
226
|
+
*/
|
|
227
|
+
export declare class RateLimiter {
|
|
228
|
+
private tokens;
|
|
229
|
+
private lastRefill;
|
|
230
|
+
private readonly maxTokens;
|
|
231
|
+
private readonly refillRate;
|
|
232
|
+
/**
|
|
233
|
+
* Create a rate limiter
|
|
234
|
+
* @param maxTokens Maximum tokens in the bucket
|
|
235
|
+
* @param refillRate Tokens added per second
|
|
236
|
+
*/
|
|
237
|
+
constructor(maxTokens: number, refillRate: number);
|
|
238
|
+
/**
|
|
239
|
+
* Try to consume tokens
|
|
240
|
+
* @returns true if tokens were available, false if rate limited
|
|
241
|
+
*/
|
|
242
|
+
tryConsume(count?: number): boolean;
|
|
243
|
+
/**
|
|
244
|
+
* Get current token count
|
|
245
|
+
*/
|
|
246
|
+
getTokens(): number;
|
|
247
|
+
/**
|
|
248
|
+
* Check if rate limited (without consuming)
|
|
249
|
+
*/
|
|
250
|
+
isLimited(): boolean;
|
|
251
|
+
private refill;
|
|
252
|
+
}
|
|
253
|
+
export {};
|
|
254
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../ts/validation.ts"],"names":[],"mappings":"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"}
|