@axeptio/behavior-detection 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/behavior-detection.esm.min.js +1 -1
- package/dist/behavior-detection.esm.min.js.map +3 -3
- package/dist/behavior-detection.min.js +1 -1
- package/dist/behavior-detection.min.js.map +3 -3
- package/dist/behavior-detector.d.ts +3 -0
- package/dist/cjs/index.cjs +30 -3
- package/dist/esm/behavior-detector.d.ts +3 -0
- package/dist/esm/behavior-detector.js +33 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/strategies/mouse.js +1 -1
- package/dist/esm/strategies/scroll.js +1 -1
- package/dist/esm/strategy.d.ts +33 -0
- package/dist/index.d.ts +1 -1
- package/dist/strategy.d.ts +33 -0
- package/package.json +1 -1
|
@@ -15,6 +15,9 @@ export declare class BehaviorDetector {
|
|
|
15
15
|
private confidenceScore;
|
|
16
16
|
private readonly CONFIDENCE_TARGET;
|
|
17
17
|
private readonly CONFIDENCE_DECAY;
|
|
18
|
+
private scoreMemory;
|
|
19
|
+
private scoreFloor;
|
|
20
|
+
private lastEventTime;
|
|
18
21
|
constructor(tickOptions?: TickOptions);
|
|
19
22
|
/**
|
|
20
23
|
* Add a detection strategy
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
46
|
// dist/esm/behavior-detector.js
|
|
47
47
|
var BehaviorDetector = class {
|
|
48
48
|
constructor(tickOptions) {
|
|
49
|
+
var _a, _b, _c, _d;
|
|
49
50
|
this.strategies = /* @__PURE__ */ new Map();
|
|
50
51
|
this.isTracking = false;
|
|
51
52
|
this.isPausedByVisibility = false;
|
|
@@ -56,12 +57,21 @@ var BehaviorDetector = class {
|
|
|
56
57
|
this.confidenceScore = 0;
|
|
57
58
|
this.CONFIDENCE_TARGET = 1;
|
|
58
59
|
this.CONFIDENCE_DECAY = 0.95;
|
|
60
|
+
this.scoreFloor = 1;
|
|
61
|
+
this.lastEventTime = 0;
|
|
59
62
|
if (tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.interval) {
|
|
60
63
|
this.tickIntervalMs = tickOptions.interval;
|
|
61
64
|
}
|
|
62
65
|
if ((tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.pauseOnHidden) !== void 0) {
|
|
63
66
|
this.pauseOnHidden = tickOptions.pauseOnHidden;
|
|
64
67
|
}
|
|
68
|
+
const mem = tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.scoreMemory;
|
|
69
|
+
this.scoreMemory = {
|
|
70
|
+
enabled: (_a = mem === null || mem === void 0 ? void 0 : mem.enabled) !== null && _a !== void 0 ? _a : true,
|
|
71
|
+
inactivityThreshold: (_b = mem === null || mem === void 0 ? void 0 : mem.inactivityThreshold) !== null && _b !== void 0 ? _b : 2e3,
|
|
72
|
+
maxRecovery: (_c = mem === null || mem === void 0 ? void 0 : mem.maxRecovery) !== null && _c !== void 0 ? _c : 0.1,
|
|
73
|
+
recoveryPerEvent: (_d = mem === null || mem === void 0 ? void 0 : mem.recoveryPerEvent) !== null && _d !== void 0 ? _d : 0.02
|
|
74
|
+
};
|
|
65
75
|
}
|
|
66
76
|
/**
|
|
67
77
|
* Add a detection strategy
|
|
@@ -90,6 +100,10 @@ var BehaviorDetector = class {
|
|
|
90
100
|
this.confidenceScore *= this.CONFIDENCE_DECAY;
|
|
91
101
|
const contribution = event.weight * strategyWeight;
|
|
92
102
|
this.confidenceScore = Math.min(this.CONFIDENCE_TARGET, this.confidenceScore + contribution);
|
|
103
|
+
this.lastEventTime = Date.now();
|
|
104
|
+
if (this.scoreMemory.enabled) {
|
|
105
|
+
this.scoreFloor = Math.min(1, this.scoreFloor + this.scoreMemory.recoveryPerEvent);
|
|
106
|
+
}
|
|
93
107
|
}
|
|
94
108
|
/**
|
|
95
109
|
* Remove a detection strategy
|
|
@@ -170,6 +184,8 @@ var BehaviorDetector = class {
|
|
|
170
184
|
*/
|
|
171
185
|
reset() {
|
|
172
186
|
this.confidenceScore = 0;
|
|
187
|
+
this.scoreFloor = 1;
|
|
188
|
+
this.lastEventTime = 0;
|
|
173
189
|
for (const [_, config] of this.strategies) {
|
|
174
190
|
config.strategy.reset();
|
|
175
191
|
}
|
|
@@ -179,8 +195,19 @@ var BehaviorDetector = class {
|
|
|
179
195
|
*/
|
|
180
196
|
async score(options = {}) {
|
|
181
197
|
const breakdown = this.calculateStrategyScore();
|
|
198
|
+
let effectiveScore = breakdown.overall;
|
|
199
|
+
if (this.scoreMemory.enabled && this.lastEventTime > 0) {
|
|
200
|
+
if (effectiveScore < this.scoreFloor) {
|
|
201
|
+
this.scoreFloor = effectiveScore;
|
|
202
|
+
}
|
|
203
|
+
const timeSinceEvent = Date.now() - this.lastEventTime;
|
|
204
|
+
if (timeSinceEvent > this.scoreMemory.inactivityThreshold) {
|
|
205
|
+
const cap = this.scoreFloor + this.scoreMemory.maxRecovery;
|
|
206
|
+
effectiveScore = Math.min(effectiveScore, cap);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
182
209
|
const result = {
|
|
183
|
-
score:
|
|
210
|
+
score: effectiveScore
|
|
184
211
|
};
|
|
185
212
|
if (options.breakdown) {
|
|
186
213
|
result.breakdown = breakdown;
|
|
@@ -398,7 +425,7 @@ var MouseStrategy = class extends BaseStrategy {
|
|
|
398
425
|
this.lastPosition = null;
|
|
399
426
|
this.lastAngle = 0;
|
|
400
427
|
this.cumulativeAngle = 0;
|
|
401
|
-
this.rollingWindowMs =
|
|
428
|
+
this.rollingWindowMs = 3e4;
|
|
402
429
|
this.listener = null;
|
|
403
430
|
this.leaveListener = null;
|
|
404
431
|
this.enterListener = null;
|
|
@@ -681,7 +708,7 @@ var ScrollStrategy = class extends BaseStrategy {
|
|
|
681
708
|
this.velocitySeries = [];
|
|
682
709
|
this.lastScrollY = null;
|
|
683
710
|
this.lastTimestamp = 0;
|
|
684
|
-
this.rollingWindowMs =
|
|
711
|
+
this.rollingWindowMs = 3e4;
|
|
685
712
|
this.documentHeight = 1;
|
|
686
713
|
this.listener = null;
|
|
687
714
|
this.isActive = false;
|
|
@@ -15,6 +15,9 @@ export declare class BehaviorDetector {
|
|
|
15
15
|
private confidenceScore;
|
|
16
16
|
private readonly CONFIDENCE_TARGET;
|
|
17
17
|
private readonly CONFIDENCE_DECAY;
|
|
18
|
+
private scoreMemory;
|
|
19
|
+
private scoreFloor;
|
|
20
|
+
private lastEventTime;
|
|
18
21
|
constructor(tickOptions?: TickOptions);
|
|
19
22
|
/**
|
|
20
23
|
* Add a detection strategy
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export class BehaviorDetector {
|
|
6
6
|
constructor(tickOptions) {
|
|
7
|
+
var _a, _b, _c, _d;
|
|
7
8
|
// Strategy mode
|
|
8
9
|
this.strategies = new Map();
|
|
9
10
|
this.isTracking = false;
|
|
@@ -16,12 +17,22 @@ export class BehaviorDetector {
|
|
|
16
17
|
this.confidenceScore = 0;
|
|
17
18
|
this.CONFIDENCE_TARGET = 1.0; // Target confidence for reliable classification
|
|
18
19
|
this.CONFIDENCE_DECAY = 0.95; // Per event decay to prevent infinite growth
|
|
20
|
+
this.scoreFloor = 1.0;
|
|
21
|
+
this.lastEventTime = 0;
|
|
19
22
|
if (tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.interval) {
|
|
20
23
|
this.tickIntervalMs = tickOptions.interval;
|
|
21
24
|
}
|
|
22
25
|
if ((tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.pauseOnHidden) !== undefined) {
|
|
23
26
|
this.pauseOnHidden = tickOptions.pauseOnHidden;
|
|
24
27
|
}
|
|
28
|
+
// Score memory defaults
|
|
29
|
+
const mem = tickOptions === null || tickOptions === void 0 ? void 0 : tickOptions.scoreMemory;
|
|
30
|
+
this.scoreMemory = {
|
|
31
|
+
enabled: (_a = mem === null || mem === void 0 ? void 0 : mem.enabled) !== null && _a !== void 0 ? _a : true,
|
|
32
|
+
inactivityThreshold: (_b = mem === null || mem === void 0 ? void 0 : mem.inactivityThreshold) !== null && _b !== void 0 ? _b : 2000,
|
|
33
|
+
maxRecovery: (_c = mem === null || mem === void 0 ? void 0 : mem.maxRecovery) !== null && _c !== void 0 ? _c : 0.1,
|
|
34
|
+
recoveryPerEvent: (_d = mem === null || mem === void 0 ? void 0 : mem.recoveryPerEvent) !== null && _d !== void 0 ? _d : 0.02,
|
|
35
|
+
};
|
|
25
36
|
}
|
|
26
37
|
/**
|
|
27
38
|
* Add a detection strategy
|
|
@@ -55,6 +66,11 @@ export class BehaviorDetector {
|
|
|
55
66
|
// eventWeight (0-1) * strategyWeight (e.g. 0.3 for mouse) = contribution
|
|
56
67
|
const contribution = event.weight * strategyWeight;
|
|
57
68
|
this.confidenceScore = Math.min(this.CONFIDENCE_TARGET, this.confidenceScore + contribution);
|
|
69
|
+
// Score memory: track activity and slowly raise the floor
|
|
70
|
+
this.lastEventTime = Date.now();
|
|
71
|
+
if (this.scoreMemory.enabled) {
|
|
72
|
+
this.scoreFloor = Math.min(1.0, this.scoreFloor + this.scoreMemory.recoveryPerEvent);
|
|
73
|
+
}
|
|
58
74
|
}
|
|
59
75
|
/**
|
|
60
76
|
* Remove a detection strategy
|
|
@@ -144,6 +160,8 @@ export class BehaviorDetector {
|
|
|
144
160
|
*/
|
|
145
161
|
reset() {
|
|
146
162
|
this.confidenceScore = 0;
|
|
163
|
+
this.scoreFloor = 1.0;
|
|
164
|
+
this.lastEventTime = 0;
|
|
147
165
|
for (const [_, config] of this.strategies) {
|
|
148
166
|
config.strategy.reset();
|
|
149
167
|
}
|
|
@@ -153,8 +171,22 @@ export class BehaviorDetector {
|
|
|
153
171
|
*/
|
|
154
172
|
async score(options = {}) {
|
|
155
173
|
const breakdown = this.calculateStrategyScore();
|
|
174
|
+
let effectiveScore = breakdown.overall;
|
|
175
|
+
// Score memory: cap recovery during inactivity
|
|
176
|
+
if (this.scoreMemory.enabled && this.lastEventTime > 0) {
|
|
177
|
+
// Track the lowest score observed
|
|
178
|
+
if (effectiveScore < this.scoreFloor) {
|
|
179
|
+
this.scoreFloor = effectiveScore;
|
|
180
|
+
}
|
|
181
|
+
// If inactive, prevent the score from recovering freely
|
|
182
|
+
const timeSinceEvent = Date.now() - this.lastEventTime;
|
|
183
|
+
if (timeSinceEvent > this.scoreMemory.inactivityThreshold) {
|
|
184
|
+
const cap = this.scoreFloor + this.scoreMemory.maxRecovery;
|
|
185
|
+
effectiveScore = Math.min(effectiveScore, cap);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
156
188
|
const result = {
|
|
157
|
-
score:
|
|
189
|
+
score: effectiveScore,
|
|
158
190
|
};
|
|
159
191
|
if (options.breakdown) {
|
|
160
192
|
result.breakdown = breakdown;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
34
|
export { BehaviorDetector } from './behavior-detector.js';
|
|
35
|
-
export type { DetectionStrategy, StrategyConfig } from './strategy.js';
|
|
35
|
+
export type { DetectionStrategy, StrategyConfig, ScoreMemoryOptions } from './strategy.js';
|
|
36
36
|
export { Mouse, Scroll, Click, Tap, Keyboard, Environment, Resize, Timing, Visibility, MouseStrategy, ScrollStrategy, ClickStrategy, TapStrategy, KeyboardStrategy, EnvironmentStrategy, ResizeStrategy, TimingStrategy, VisibilityStrategy, } from './strategies/index.js';
|
|
37
37
|
export type { BehaviorSettings, ScoreOptions, ScoreResult, ScoreBreakdown, TrackedEvent, EventType, ScoringFunction, } from './types.js';
|
|
38
38
|
export { DEFAULT_SETTINGS } from './types.js';
|
|
@@ -20,7 +20,7 @@ export class MouseStrategy extends BaseStrategy {
|
|
|
20
20
|
this.lastPosition = null;
|
|
21
21
|
this.lastAngle = 0;
|
|
22
22
|
this.cumulativeAngle = 0;
|
|
23
|
-
this.rollingWindowMs =
|
|
23
|
+
this.rollingWindowMs = 30000;
|
|
24
24
|
this.listener = null;
|
|
25
25
|
this.leaveListener = null;
|
|
26
26
|
this.enterListener = null;
|
|
@@ -14,7 +14,7 @@ export class ScrollStrategy extends BaseStrategy {
|
|
|
14
14
|
this.velocitySeries = [];
|
|
15
15
|
this.lastScrollY = null;
|
|
16
16
|
this.lastTimestamp = 0;
|
|
17
|
-
this.rollingWindowMs =
|
|
17
|
+
this.rollingWindowMs = 30000;
|
|
18
18
|
this.documentHeight = 1;
|
|
19
19
|
this.listener = null;
|
|
20
20
|
this.isActive = false;
|
package/dist/esm/strategy.d.ts
CHANGED
|
@@ -104,4 +104,37 @@ export interface TickOptions {
|
|
|
104
104
|
* Default: true (recommended for better performance and battery life)
|
|
105
105
|
*/
|
|
106
106
|
pauseOnHidden?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Score memory options to prevent score recovery during inactivity.
|
|
109
|
+
* When enabled, the detector remembers the lowest score observed and prevents
|
|
110
|
+
* the score from jumping back up when behavioral data expires from rolling windows.
|
|
111
|
+
* Default: enabled with sensible defaults
|
|
112
|
+
*/
|
|
113
|
+
scoreMemory?: ScoreMemoryOptions;
|
|
114
|
+
}
|
|
115
|
+
export interface ScoreMemoryOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Enable score memory (default: true)
|
|
118
|
+
* When enabled, the detector tracks the lowest score observed and caps
|
|
119
|
+
* score recovery during periods of inactivity.
|
|
120
|
+
*/
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Milliseconds of inactivity before the score cap kicks in (default: 2000)
|
|
124
|
+
* If no strategy events are received for this duration, the score cannot
|
|
125
|
+
* recover freely — it's capped near the lowest observed score.
|
|
126
|
+
*/
|
|
127
|
+
inactivityThreshold?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Maximum score increase allowed above the floor during inactivity (default: 0.1)
|
|
130
|
+
* During inactivity, effective score = min(rawScore, floor + maxRecovery)
|
|
131
|
+
*/
|
|
132
|
+
maxRecovery?: number;
|
|
133
|
+
/**
|
|
134
|
+
* How much the floor rises per strategy event (default: 0.02)
|
|
135
|
+
* Each incoming event nudges the floor upward, allowing genuine human
|
|
136
|
+
* activity to eventually recover the score. At 0.02, it takes ~15 events
|
|
137
|
+
* to recover 0.3 points of score.
|
|
138
|
+
*/
|
|
139
|
+
recoveryPerEvent?: number;
|
|
107
140
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
34
|
export { BehaviorDetector } from './behavior-detector.js';
|
|
35
|
-
export type { DetectionStrategy, StrategyConfig } from './strategy.js';
|
|
35
|
+
export type { DetectionStrategy, StrategyConfig, ScoreMemoryOptions } from './strategy.js';
|
|
36
36
|
export { Mouse, Scroll, Click, Tap, Keyboard, Environment, Resize, Timing, Visibility, MouseStrategy, ScrollStrategy, ClickStrategy, TapStrategy, KeyboardStrategy, EnvironmentStrategy, ResizeStrategy, TimingStrategy, VisibilityStrategy, } from './strategies/index.js';
|
|
37
37
|
export type { BehaviorSettings, ScoreOptions, ScoreResult, ScoreBreakdown, TrackedEvent, EventType, ScoringFunction, } from './types.js';
|
|
38
38
|
export { DEFAULT_SETTINGS } from './types.js';
|
package/dist/strategy.d.ts
CHANGED
|
@@ -104,4 +104,37 @@ export interface TickOptions {
|
|
|
104
104
|
* Default: true (recommended for better performance and battery life)
|
|
105
105
|
*/
|
|
106
106
|
pauseOnHidden?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Score memory options to prevent score recovery during inactivity.
|
|
109
|
+
* When enabled, the detector remembers the lowest score observed and prevents
|
|
110
|
+
* the score from jumping back up when behavioral data expires from rolling windows.
|
|
111
|
+
* Default: enabled with sensible defaults
|
|
112
|
+
*/
|
|
113
|
+
scoreMemory?: ScoreMemoryOptions;
|
|
114
|
+
}
|
|
115
|
+
export interface ScoreMemoryOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Enable score memory (default: true)
|
|
118
|
+
* When enabled, the detector tracks the lowest score observed and caps
|
|
119
|
+
* score recovery during periods of inactivity.
|
|
120
|
+
*/
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Milliseconds of inactivity before the score cap kicks in (default: 2000)
|
|
124
|
+
* If no strategy events are received for this duration, the score cannot
|
|
125
|
+
* recover freely — it's capped near the lowest observed score.
|
|
126
|
+
*/
|
|
127
|
+
inactivityThreshold?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Maximum score increase allowed above the floor during inactivity (default: 0.1)
|
|
130
|
+
* During inactivity, effective score = min(rawScore, floor + maxRecovery)
|
|
131
|
+
*/
|
|
132
|
+
maxRecovery?: number;
|
|
133
|
+
/**
|
|
134
|
+
* How much the floor rises per strategy event (default: 0.02)
|
|
135
|
+
* Each incoming event nudges the floor upward, allowing genuine human
|
|
136
|
+
* activity to eventually recover the score. At 0.02, it takes ~15 events
|
|
137
|
+
* to recover 0.3 points of score.
|
|
138
|
+
*/
|
|
139
|
+
recoveryPerEvent?: number;
|
|
107
140
|
}
|
package/package.json
CHANGED