@trentapps/manager-protocol 1.1.3 → 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.
Files changed (142) hide show
  1. package/README.md +28 -0
  2. package/dist/analyzers/CSSAnalyzer.d.ts +180 -8
  3. package/dist/analyzers/CSSAnalyzer.d.ts.map +1 -1
  4. package/dist/analyzers/CSSAnalyzer.js +561 -105
  5. package/dist/analyzers/CSSAnalyzer.js.map +1 -1
  6. package/dist/config/dashboard.d.ts +55 -0
  7. package/dist/config/dashboard.d.ts.map +1 -0
  8. package/dist/config/dashboard.js +103 -0
  9. package/dist/config/dashboard.js.map +1 -0
  10. package/dist/config/index.d.ts +7 -0
  11. package/dist/config/index.d.ts.map +1 -0
  12. package/dist/config/index.js +7 -0
  13. package/dist/config/index.js.map +1 -0
  14. package/dist/dashboard/httpDashboard.d.ts +100 -0
  15. package/dist/dashboard/httpDashboard.d.ts.map +1 -0
  16. package/dist/dashboard/httpDashboard.js +1276 -0
  17. package/dist/dashboard/httpDashboard.js.map +1 -0
  18. package/dist/dashboard/index.d.ts +6 -0
  19. package/dist/dashboard/index.d.ts.map +1 -0
  20. package/dist/dashboard/index.js +7 -0
  21. package/dist/dashboard/index.js.map +1 -0
  22. package/dist/engine/AuditLogger.d.ts +370 -2
  23. package/dist/engine/AuditLogger.d.ts.map +1 -1
  24. package/dist/engine/AuditLogger.js +1064 -24
  25. package/dist/engine/AuditLogger.js.map +1 -1
  26. package/dist/engine/GitHubClient.d.ts +183 -0
  27. package/dist/engine/GitHubClient.d.ts.map +1 -0
  28. package/dist/engine/GitHubClient.js +411 -0
  29. package/dist/engine/GitHubClient.js.map +1 -0
  30. package/dist/engine/RateLimiter.d.ts +5 -3
  31. package/dist/engine/RateLimiter.d.ts.map +1 -1
  32. package/dist/engine/RateLimiter.js +49 -72
  33. package/dist/engine/RateLimiter.js.map +1 -1
  34. package/dist/engine/RuleDependencyAnalyzer.d.ts +73 -0
  35. package/dist/engine/RuleDependencyAnalyzer.d.ts.map +1 -0
  36. package/dist/engine/RuleDependencyAnalyzer.js +475 -0
  37. package/dist/engine/RuleDependencyAnalyzer.js.map +1 -0
  38. package/dist/engine/RulesEngine.d.ts +102 -3
  39. package/dist/engine/RulesEngine.d.ts.map +1 -1
  40. package/dist/engine/RulesEngine.js +326 -21
  41. package/dist/engine/RulesEngine.js.map +1 -1
  42. package/dist/engine/TaskManager.d.ts +10 -14
  43. package/dist/engine/TaskManager.d.ts.map +1 -1
  44. package/dist/engine/TaskManager.js +169 -197
  45. package/dist/engine/TaskManager.js.map +1 -1
  46. package/dist/engine/index.d.ts +3 -0
  47. package/dist/engine/index.d.ts.map +1 -1
  48. package/dist/engine/index.js +5 -0
  49. package/dist/engine/index.js.map +1 -1
  50. package/dist/rules/azure.d.ts.map +1 -1
  51. package/dist/rules/azure.js +12 -14
  52. package/dist/rules/azure.js.map +1 -1
  53. package/dist/rules/compliance.d.ts.map +1 -1
  54. package/dist/rules/compliance.js +23 -41
  55. package/dist/rules/compliance.js.map +1 -1
  56. package/dist/rules/condition-optimizer.d.ts +151 -0
  57. package/dist/rules/condition-optimizer.d.ts.map +1 -0
  58. package/dist/rules/condition-optimizer.js +479 -0
  59. package/dist/rules/condition-optimizer.js.map +1 -0
  60. package/dist/rules/css.d.ts.map +1 -1
  61. package/dist/rules/css.js +538 -0
  62. package/dist/rules/css.js.map +1 -1
  63. package/dist/rules/field-standards.d.ts +1172 -0
  64. package/dist/rules/field-standards.d.ts.map +1 -0
  65. package/dist/rules/field-standards.js +908 -0
  66. package/dist/rules/field-standards.js.map +1 -0
  67. package/dist/rules/flask.d.ts.map +1 -1
  68. package/dist/rules/flask.js +18 -31
  69. package/dist/rules/flask.js.map +1 -1
  70. package/dist/rules/index.d.ts +220 -0
  71. package/dist/rules/index.d.ts.map +1 -1
  72. package/dist/rules/index.js +155 -0
  73. package/dist/rules/index.js.map +1 -1
  74. package/dist/rules/ml-ai.d.ts.map +1 -1
  75. package/dist/rules/ml-ai.js +11 -13
  76. package/dist/rules/ml-ai.js.map +1 -1
  77. package/dist/rules/patterns.d.ts +568 -0
  78. package/dist/rules/patterns.d.ts.map +1 -0
  79. package/dist/rules/patterns.js +1359 -0
  80. package/dist/rules/patterns.js.map +1 -0
  81. package/dist/rules/security.d.ts.map +1 -1
  82. package/dist/rules/security.js +580 -19
  83. package/dist/rules/security.js.map +1 -1
  84. package/dist/rules/shared-patterns.d.ts +268 -0
  85. package/dist/rules/shared-patterns.d.ts.map +1 -0
  86. package/dist/rules/shared-patterns.js +556 -0
  87. package/dist/rules/shared-patterns.js.map +1 -0
  88. package/dist/rules/storage.d.ts +8 -2
  89. package/dist/rules/storage.d.ts.map +1 -1
  90. package/dist/rules/storage.js +541 -3
  91. package/dist/rules/storage.js.map +1 -1
  92. package/dist/rules/stripe.d.ts.map +1 -1
  93. package/dist/rules/stripe.js +19 -26
  94. package/dist/rules/stripe.js.map +1 -1
  95. package/dist/rules/websocket.d.ts.map +1 -1
  96. package/dist/rules/websocket.js +32 -40
  97. package/dist/rules/websocket.js.map +1 -1
  98. package/dist/supervisor/AgentSupervisor.d.ts +52 -0
  99. package/dist/supervisor/AgentSupervisor.d.ts.map +1 -1
  100. package/dist/supervisor/AgentSupervisor.js +120 -1
  101. package/dist/supervisor/AgentSupervisor.js.map +1 -1
  102. package/dist/supervisor/ManagedServerRegistry.d.ts +139 -2
  103. package/dist/supervisor/ManagedServerRegistry.d.ts.map +1 -1
  104. package/dist/supervisor/ManagedServerRegistry.js +590 -6
  105. package/dist/supervisor/ManagedServerRegistry.js.map +1 -1
  106. package/dist/supervisor/ProjectTracker.d.ts +2 -1
  107. package/dist/supervisor/ProjectTracker.d.ts.map +1 -1
  108. package/dist/supervisor/ProjectTracker.js +5 -9
  109. package/dist/supervisor/ProjectTracker.js.map +1 -1
  110. package/dist/testing/index.d.ts +11 -0
  111. package/dist/testing/index.d.ts.map +1 -0
  112. package/dist/testing/index.js +12 -0
  113. package/dist/testing/index.js.map +1 -0
  114. package/dist/testing/rule-tester.d.ts +217 -0
  115. package/dist/testing/rule-tester.d.ts.map +1 -0
  116. package/dist/testing/rule-tester.examples.d.ts +57 -0
  117. package/dist/testing/rule-tester.examples.d.ts.map +1 -0
  118. package/dist/testing/rule-tester.examples.js +375 -0
  119. package/dist/testing/rule-tester.examples.js.map +1 -0
  120. package/dist/testing/rule-tester.js +381 -0
  121. package/dist/testing/rule-tester.js.map +1 -0
  122. package/dist/testing/rule-validator.d.ts +141 -0
  123. package/dist/testing/rule-validator.d.ts.map +1 -0
  124. package/dist/testing/rule-validator.js +640 -0
  125. package/dist/testing/rule-validator.js.map +1 -0
  126. package/dist/types/index.d.ts +265 -4
  127. package/dist/types/index.d.ts.map +1 -1
  128. package/dist/types/index.js +57 -2
  129. package/dist/types/index.js.map +1 -1
  130. package/dist/utils/index.d.ts +2 -0
  131. package/dist/utils/index.d.ts.map +1 -1
  132. package/dist/utils/index.js +2 -0
  133. package/dist/utils/index.js.map +1 -1
  134. package/dist/utils/rate-limiting.d.ts +268 -0
  135. package/dist/utils/rate-limiting.d.ts.map +1 -0
  136. package/dist/utils/rate-limiting.js +403 -0
  137. package/dist/utils/rate-limiting.js.map +1 -0
  138. package/dist/utils/shared.d.ts +306 -0
  139. package/dist/utils/shared.d.ts.map +1 -0
  140. package/dist/utils/shared.js +464 -0
  141. package/dist/utils/shared.js.map +1 -0
  142. package/package.json +2 -1
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Enterprise Agent Supervisor - Rate Limiting Utilities
3
+ *
4
+ * Reusable utilities for rate limiting:
5
+ * - Bucket key building for different scopes
6
+ * - Sliding window time-based tracking
7
+ */
8
+ /**
9
+ * Scope types for rate limit bucket keys
10
+ */
11
+ export type BucketScope = 'global' | 'agent' | 'session' | 'user' | 'action_type';
12
+ /**
13
+ * Identifiers used to build bucket keys
14
+ */
15
+ export interface BucketIdentifiers {
16
+ agentId?: string;
17
+ sessionId?: string;
18
+ userId?: string;
19
+ actionType?: string;
20
+ }
21
+ /**
22
+ * Window algorithm types
23
+ */
24
+ export type WindowAlgorithm = 'fixed' | 'sliding';
25
+ /**
26
+ * Statistics for a time window
27
+ */
28
+ export interface WindowStats {
29
+ /** Number of requests in the current window */
30
+ count: number;
31
+ /** Number of requests remaining before limit */
32
+ remaining: number;
33
+ /** Timestamp when the window started (ms since epoch) */
34
+ windowStart: number;
35
+ /** Timestamp when the window resets (ms since epoch) */
36
+ resetAt: number;
37
+ /** ISO string of reset time */
38
+ resetAtISO: string;
39
+ /** Whether the limit has been exceeded */
40
+ exceeded: boolean;
41
+ /** Percentage of limit used (0-100) */
42
+ usagePercent: number;
43
+ }
44
+ /**
45
+ * Configuration for SlidingWindow
46
+ */
47
+ export interface SlidingWindowConfig {
48
+ /** Window duration in milliseconds */
49
+ windowMs: number;
50
+ /** Maximum requests allowed in the window */
51
+ maxRequests: number;
52
+ /** Optional burst limit for short-term spikes */
53
+ burstLimit?: number;
54
+ /** Window algorithm: 'fixed' resets at boundaries, 'sliding' moves with time */
55
+ algorithm?: WindowAlgorithm;
56
+ }
57
+ /**
58
+ * Build a bucket key based on scope and identifiers.
59
+ *
60
+ * Key format: `{prefix}:{scope}:{identifier}`
61
+ *
62
+ * This creates consistent, collision-free keys for rate limit buckets.
63
+ *
64
+ * @param scope - The scope for the bucket (global, agent, session, user, action_type)
65
+ * @param identifiers - Object containing identifier values
66
+ * @param prefix - Optional prefix for namespacing (e.g., config ID)
67
+ * @returns A unique bucket key string
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Global scope
72
+ * buildBucketKey('global', {}) // "global"
73
+ * buildBucketKey('global', {}, 'rate-1') // "rate-1:global"
74
+ *
75
+ * // Agent scope
76
+ * buildBucketKey('agent', { agentId: 'agent-123' }) // "agent:agent-123"
77
+ *
78
+ * // Session scope with prefix
79
+ * buildBucketKey('session', { sessionId: 'sess-456' }, 'api-limit')
80
+ * // "api-limit:session:sess-456"
81
+ * ```
82
+ */
83
+ export declare function buildBucketKey(scope: BucketScope, identifiers: BucketIdentifiers, prefix?: string): string;
84
+ /**
85
+ * Parse a bucket key to extract scope and identifier.
86
+ *
87
+ * @param key - The bucket key to parse
88
+ * @returns Object with scope and identifier, or null if invalid
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * parseBucketKey('rate-1:agent:agent-123')
93
+ * // { prefix: 'rate-1', scope: 'agent', identifier: 'agent-123' }
94
+ *
95
+ * parseBucketKey('global')
96
+ * // { prefix: undefined, scope: 'global', identifier: undefined }
97
+ * ```
98
+ */
99
+ export declare function parseBucketKey(key: string): {
100
+ prefix?: string;
101
+ scope: BucketScope | 'unknown';
102
+ identifier?: string;
103
+ } | null;
104
+ /**
105
+ * SlidingWindow class for time-based window tracking.
106
+ *
107
+ * Supports both fixed and sliding window algorithms:
108
+ * - Fixed: Window resets at fixed boundaries (simpler, less memory)
109
+ * - Sliding: Window slides with time (more accurate, tracks individual requests)
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Create a window: 100 requests per minute
114
+ * const window = new SlidingWindow({
115
+ * windowMs: 60000,
116
+ * maxRequests: 100,
117
+ * algorithm: 'fixed'
118
+ * });
119
+ *
120
+ * // Check and record a request
121
+ * if (window.canAccept()) {
122
+ * window.record();
123
+ * // Process request
124
+ * } else {
125
+ * // Rate limited
126
+ * const stats = window.getStats();
127
+ * console.log(`Retry after ${stats.resetAt}`);
128
+ * }
129
+ * ```
130
+ */
131
+ export declare class SlidingWindow {
132
+ private config;
133
+ private count;
134
+ private burstCount;
135
+ private windowStart;
136
+ private requestTimestamps;
137
+ constructor(config: SlidingWindowConfig);
138
+ /**
139
+ * Check if the window has expired and needs reset.
140
+ *
141
+ * For fixed windows: Checks if current time is past window boundary.
142
+ * For sliding windows: Always returns false (sliding handles this differently).
143
+ *
144
+ * @param now - Current timestamp (defaults to Date.now())
145
+ * @returns Whether the window has expired
146
+ */
147
+ isExpired(now?: number): boolean;
148
+ /**
149
+ * Reset the window to initial state.
150
+ *
151
+ * @param now - Timestamp to use as new window start (defaults to Date.now())
152
+ */
153
+ reset(now?: number): void;
154
+ /**
155
+ * Check if the window can accept another request.
156
+ * Automatically resets expired windows (for fixed algorithm).
157
+ *
158
+ * @param now - Current timestamp (defaults to Date.now())
159
+ * @returns Whether a request can be accepted
160
+ */
161
+ canAccept(now?: number): boolean;
162
+ /**
163
+ * Check if the window can accept based on burst limit only.
164
+ *
165
+ * @param now - Current timestamp (defaults to Date.now())
166
+ * @returns Whether burst limit allows acceptance
167
+ */
168
+ canAcceptBurst(now?: number): boolean;
169
+ /**
170
+ * Record a request in the window.
171
+ *
172
+ * @param now - Current timestamp (defaults to Date.now())
173
+ */
174
+ record(now?: number): void;
175
+ /**
176
+ * Get current window statistics.
177
+ *
178
+ * @param now - Current timestamp (defaults to Date.now())
179
+ * @returns WindowStats object with current state
180
+ */
181
+ getStats(now?: number): WindowStats;
182
+ /**
183
+ * Get the current count of requests in the window.
184
+ *
185
+ * @param now - Current timestamp (defaults to Date.now())
186
+ * @returns Current request count
187
+ */
188
+ getCount(now?: number): number;
189
+ /**
190
+ * Get remaining requests before limit is hit.
191
+ *
192
+ * @param now - Current timestamp (defaults to Date.now())
193
+ * @returns Number of remaining requests
194
+ */
195
+ getRemaining(now?: number): number;
196
+ /**
197
+ * Get timestamp when the window resets.
198
+ *
199
+ * @returns Reset timestamp in milliseconds since epoch
200
+ */
201
+ getResetTime(): number;
202
+ /**
203
+ * Get the window configuration.
204
+ *
205
+ * @returns The window configuration
206
+ */
207
+ getConfig(): Required<SlidingWindowConfig>;
208
+ /**
209
+ * Set internal state (useful for persistence/restoration).
210
+ *
211
+ * @param state - State to restore
212
+ */
213
+ setState(state: {
214
+ count: number;
215
+ windowStart: number;
216
+ burstCount?: number;
217
+ }): void;
218
+ /**
219
+ * Get internal state (useful for persistence).
220
+ *
221
+ * @returns Current internal state
222
+ */
223
+ getState(): {
224
+ count: number;
225
+ windowStart: number;
226
+ burstCount: number;
227
+ };
228
+ private maybeResetWindow;
229
+ private getSlidingCount;
230
+ private cleanupOldTimestamps;
231
+ }
232
+ /**
233
+ * Create a sliding window with common presets.
234
+ *
235
+ * @param preset - Preset name
236
+ * @returns Configured SlidingWindow
237
+ *
238
+ * @example
239
+ * ```typescript
240
+ * // 60 requests per minute
241
+ * const perMinute = createWindowPreset('per-minute');
242
+ *
243
+ * // 1000 requests per hour
244
+ * const perHour = createWindowPreset('per-hour');
245
+ * ```
246
+ */
247
+ export declare function createWindowPreset(preset: 'per-second' | 'per-minute' | 'per-hour' | 'per-day'): SlidingWindow;
248
+ /**
249
+ * Create multiple bucket keys for different scopes from the same identifiers.
250
+ *
251
+ * @param identifiers - Identifiers to use
252
+ * @param prefix - Optional prefix for all keys
253
+ * @returns Object with keys for each scope
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const keys = createBucketKeys({ agentId: 'a1', userId: 'u1' }, 'rate');
258
+ * // {
259
+ * // global: 'rate:global',
260
+ * // agent: 'rate:agent:a1',
261
+ * // user: 'rate:user:u1',
262
+ * // session: 'rate:session:unknown',
263
+ * // action_type: 'rate:action:unknown'
264
+ * // }
265
+ * ```
266
+ */
267
+ export declare function createBucketKeys(identifiers: BucketIdentifiers, prefix?: string): Record<BucketScope, string>;
268
+ //# sourceMappingURL=rate-limiting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiting.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limiting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,403 @@
1
+ /**
2
+ * Enterprise Agent Supervisor - Rate Limiting Utilities
3
+ *
4
+ * Reusable utilities for rate limiting:
5
+ * - Bucket key building for different scopes
6
+ * - Sliding window time-based tracking
7
+ */
8
+ // ============================================================================
9
+ // BUCKET KEY BUILDING
10
+ // ============================================================================
11
+ /**
12
+ * Separator used in bucket keys to prevent collisions
13
+ */
14
+ const KEY_SEPARATOR = ':';
15
+ /**
16
+ * Default identifier when none is provided
17
+ */
18
+ const DEFAULT_IDENTIFIER = 'unknown';
19
+ /**
20
+ * Build a bucket key based on scope and identifiers.
21
+ *
22
+ * Key format: `{prefix}:{scope}:{identifier}`
23
+ *
24
+ * This creates consistent, collision-free keys for rate limit buckets.
25
+ *
26
+ * @param scope - The scope for the bucket (global, agent, session, user, action_type)
27
+ * @param identifiers - Object containing identifier values
28
+ * @param prefix - Optional prefix for namespacing (e.g., config ID)
29
+ * @returns A unique bucket key string
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // Global scope
34
+ * buildBucketKey('global', {}) // "global"
35
+ * buildBucketKey('global', {}, 'rate-1') // "rate-1:global"
36
+ *
37
+ * // Agent scope
38
+ * buildBucketKey('agent', { agentId: 'agent-123' }) // "agent:agent-123"
39
+ *
40
+ * // Session scope with prefix
41
+ * buildBucketKey('session', { sessionId: 'sess-456' }, 'api-limit')
42
+ * // "api-limit:session:sess-456"
43
+ * ```
44
+ */
45
+ export function buildBucketKey(scope, identifiers, prefix) {
46
+ let key;
47
+ switch (scope) {
48
+ case 'global':
49
+ key = 'global';
50
+ break;
51
+ case 'agent':
52
+ key = `agent${KEY_SEPARATOR}${identifiers.agentId || DEFAULT_IDENTIFIER}`;
53
+ break;
54
+ case 'session':
55
+ key = `session${KEY_SEPARATOR}${identifiers.sessionId || DEFAULT_IDENTIFIER}`;
56
+ break;
57
+ case 'user':
58
+ key = `user${KEY_SEPARATOR}${identifiers.userId || DEFAULT_IDENTIFIER}`;
59
+ break;
60
+ case 'action_type':
61
+ key = `action${KEY_SEPARATOR}${identifiers.actionType || DEFAULT_IDENTIFIER}`;
62
+ break;
63
+ default:
64
+ key = 'unknown';
65
+ }
66
+ return prefix ? `${prefix}${KEY_SEPARATOR}${key}` : key;
67
+ }
68
+ /**
69
+ * Parse a bucket key to extract scope and identifier.
70
+ *
71
+ * @param key - The bucket key to parse
72
+ * @returns Object with scope and identifier, or null if invalid
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * parseBucketKey('rate-1:agent:agent-123')
77
+ * // { prefix: 'rate-1', scope: 'agent', identifier: 'agent-123' }
78
+ *
79
+ * parseBucketKey('global')
80
+ * // { prefix: undefined, scope: 'global', identifier: undefined }
81
+ * ```
82
+ */
83
+ export function parseBucketKey(key) {
84
+ if (!key)
85
+ return null;
86
+ const parts = key.split(KEY_SEPARATOR);
87
+ // Handle simple global key
88
+ if (parts.length === 1 && parts[0] === 'global') {
89
+ return { scope: 'global' };
90
+ }
91
+ // Handle keys without prefix: "scope:identifier"
92
+ if (parts.length === 2) {
93
+ const scopeMap = {
94
+ 'agent': 'agent',
95
+ 'session': 'session',
96
+ 'user': 'user',
97
+ 'action': 'action_type'
98
+ };
99
+ const scope = scopeMap[parts[0]];
100
+ if (scope) {
101
+ return { scope, identifier: parts[1] };
102
+ }
103
+ }
104
+ // Handle keys with prefix: "prefix:scope:identifier" or "prefix:global"
105
+ if (parts.length >= 2) {
106
+ const prefix = parts[0];
107
+ const scopePart = parts[1];
108
+ if (scopePart === 'global') {
109
+ return { prefix, scope: 'global' };
110
+ }
111
+ const scopeMap = {
112
+ 'agent': 'agent',
113
+ 'session': 'session',
114
+ 'user': 'user',
115
+ 'action': 'action_type'
116
+ };
117
+ const scope = scopeMap[scopePart];
118
+ if (scope && parts.length >= 3) {
119
+ return { prefix, scope, identifier: parts.slice(2).join(KEY_SEPARATOR) };
120
+ }
121
+ }
122
+ return { scope: 'unknown' };
123
+ }
124
+ // ============================================================================
125
+ // SLIDING WINDOW
126
+ // ============================================================================
127
+ /**
128
+ * SlidingWindow class for time-based window tracking.
129
+ *
130
+ * Supports both fixed and sliding window algorithms:
131
+ * - Fixed: Window resets at fixed boundaries (simpler, less memory)
132
+ * - Sliding: Window slides with time (more accurate, tracks individual requests)
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * // Create a window: 100 requests per minute
137
+ * const window = new SlidingWindow({
138
+ * windowMs: 60000,
139
+ * maxRequests: 100,
140
+ * algorithm: 'fixed'
141
+ * });
142
+ *
143
+ * // Check and record a request
144
+ * if (window.canAccept()) {
145
+ * window.record();
146
+ * // Process request
147
+ * } else {
148
+ * // Rate limited
149
+ * const stats = window.getStats();
150
+ * console.log(`Retry after ${stats.resetAt}`);
151
+ * }
152
+ * ```
153
+ */
154
+ export class SlidingWindow {
155
+ config;
156
+ // Fixed window state
157
+ count = 0;
158
+ burstCount = 0;
159
+ windowStart;
160
+ // Sliding window state (for sliding algorithm)
161
+ requestTimestamps = [];
162
+ constructor(config) {
163
+ this.config = {
164
+ windowMs: config.windowMs,
165
+ maxRequests: config.maxRequests,
166
+ burstLimit: config.burstLimit ?? config.maxRequests,
167
+ algorithm: config.algorithm ?? 'fixed'
168
+ };
169
+ this.windowStart = Date.now();
170
+ }
171
+ /**
172
+ * Check if the window has expired and needs reset.
173
+ *
174
+ * For fixed windows: Checks if current time is past window boundary.
175
+ * For sliding windows: Always returns false (sliding handles this differently).
176
+ *
177
+ * @param now - Current timestamp (defaults to Date.now())
178
+ * @returns Whether the window has expired
179
+ */
180
+ isExpired(now = Date.now()) {
181
+ if (this.config.algorithm === 'sliding') {
182
+ return false; // Sliding windows don't expire in the same way
183
+ }
184
+ // Fixed window: expired when now - windowStart >= windowMs
185
+ return now - this.windowStart >= this.config.windowMs;
186
+ }
187
+ /**
188
+ * Reset the window to initial state.
189
+ *
190
+ * @param now - Timestamp to use as new window start (defaults to Date.now())
191
+ */
192
+ reset(now = Date.now()) {
193
+ this.count = 0;
194
+ this.burstCount = 0;
195
+ this.windowStart = now;
196
+ this.requestTimestamps = [];
197
+ }
198
+ /**
199
+ * Check if the window can accept another request.
200
+ * Automatically resets expired windows (for fixed algorithm).
201
+ *
202
+ * @param now - Current timestamp (defaults to Date.now())
203
+ * @returns Whether a request can be accepted
204
+ */
205
+ canAccept(now = Date.now()) {
206
+ this.maybeResetWindow(now);
207
+ if (this.config.algorithm === 'sliding') {
208
+ return this.getSlidingCount(now) < this.config.maxRequests;
209
+ }
210
+ // Fixed window
211
+ if (this.count >= this.config.maxRequests) {
212
+ return false;
213
+ }
214
+ if (this.burstCount >= this.config.burstLimit) {
215
+ return false;
216
+ }
217
+ return true;
218
+ }
219
+ /**
220
+ * Check if the window can accept based on burst limit only.
221
+ *
222
+ * @param now - Current timestamp (defaults to Date.now())
223
+ * @returns Whether burst limit allows acceptance
224
+ */
225
+ canAcceptBurst(now = Date.now()) {
226
+ this.maybeResetWindow(now);
227
+ if (this.config.algorithm === 'sliding') {
228
+ // For sliding, burst is same as regular limit
229
+ return this.getSlidingCount(now) < this.config.burstLimit;
230
+ }
231
+ return this.burstCount < this.config.burstLimit;
232
+ }
233
+ /**
234
+ * Record a request in the window.
235
+ *
236
+ * @param now - Current timestamp (defaults to Date.now())
237
+ */
238
+ record(now = Date.now()) {
239
+ this.maybeResetWindow(now);
240
+ if (this.config.algorithm === 'sliding') {
241
+ this.requestTimestamps.push(now);
242
+ // Clean up old timestamps to prevent memory growth
243
+ this.cleanupOldTimestamps(now);
244
+ }
245
+ else {
246
+ this.count++;
247
+ this.burstCount++;
248
+ }
249
+ }
250
+ /**
251
+ * Get current window statistics.
252
+ *
253
+ * @param now - Current timestamp (defaults to Date.now())
254
+ * @returns WindowStats object with current state
255
+ */
256
+ getStats(now = Date.now()) {
257
+ this.maybeResetWindow(now);
258
+ const count = this.config.algorithm === 'sliding'
259
+ ? this.getSlidingCount(now)
260
+ : this.count;
261
+ const remaining = Math.max(0, this.config.maxRequests - count);
262
+ const resetAt = this.windowStart + this.config.windowMs;
263
+ return {
264
+ count,
265
+ remaining,
266
+ windowStart: this.windowStart,
267
+ resetAt,
268
+ resetAtISO: new Date(resetAt).toISOString(),
269
+ exceeded: count >= this.config.maxRequests,
270
+ usagePercent: Math.min(100, Math.round((count / this.config.maxRequests) * 100))
271
+ };
272
+ }
273
+ /**
274
+ * Get the current count of requests in the window.
275
+ *
276
+ * @param now - Current timestamp (defaults to Date.now())
277
+ * @returns Current request count
278
+ */
279
+ getCount(now = Date.now()) {
280
+ this.maybeResetWindow(now);
281
+ return this.config.algorithm === 'sliding'
282
+ ? this.getSlidingCount(now)
283
+ : this.count;
284
+ }
285
+ /**
286
+ * Get remaining requests before limit is hit.
287
+ *
288
+ * @param now - Current timestamp (defaults to Date.now())
289
+ * @returns Number of remaining requests
290
+ */
291
+ getRemaining(now = Date.now()) {
292
+ return Math.max(0, this.config.maxRequests - this.getCount(now));
293
+ }
294
+ /**
295
+ * Get timestamp when the window resets.
296
+ *
297
+ * @returns Reset timestamp in milliseconds since epoch
298
+ */
299
+ getResetTime() {
300
+ return this.windowStart + this.config.windowMs;
301
+ }
302
+ /**
303
+ * Get the window configuration.
304
+ *
305
+ * @returns The window configuration
306
+ */
307
+ getConfig() {
308
+ return { ...this.config };
309
+ }
310
+ /**
311
+ * Set internal state (useful for persistence/restoration).
312
+ *
313
+ * @param state - State to restore
314
+ */
315
+ setState(state) {
316
+ this.count = state.count;
317
+ this.windowStart = state.windowStart;
318
+ this.burstCount = state.burstCount ?? 0;
319
+ }
320
+ /**
321
+ * Get internal state (useful for persistence).
322
+ *
323
+ * @returns Current internal state
324
+ */
325
+ getState() {
326
+ return {
327
+ count: this.count,
328
+ windowStart: this.windowStart,
329
+ burstCount: this.burstCount
330
+ };
331
+ }
332
+ // Private methods
333
+ maybeResetWindow(now) {
334
+ if (this.config.algorithm === 'fixed' && this.isExpired(now)) {
335
+ this.reset(now);
336
+ }
337
+ }
338
+ getSlidingCount(now) {
339
+ const windowStart = now - this.config.windowMs;
340
+ return this.requestTimestamps.filter(ts => ts > windowStart).length;
341
+ }
342
+ cleanupOldTimestamps(now) {
343
+ const windowStart = now - this.config.windowMs;
344
+ // Keep only timestamps within the window plus a small buffer
345
+ this.requestTimestamps = this.requestTimestamps.filter(ts => ts > windowStart - 1000);
346
+ }
347
+ }
348
+ // ============================================================================
349
+ // FACTORY FUNCTIONS
350
+ // ============================================================================
351
+ /**
352
+ * Create a sliding window with common presets.
353
+ *
354
+ * @param preset - Preset name
355
+ * @returns Configured SlidingWindow
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * // 60 requests per minute
360
+ * const perMinute = createWindowPreset('per-minute');
361
+ *
362
+ * // 1000 requests per hour
363
+ * const perHour = createWindowPreset('per-hour');
364
+ * ```
365
+ */
366
+ export function createWindowPreset(preset) {
367
+ const presets = {
368
+ 'per-second': { windowMs: 1000, maxRequests: 10, algorithm: 'fixed' },
369
+ 'per-minute': { windowMs: 60000, maxRequests: 60, algorithm: 'fixed' },
370
+ 'per-hour': { windowMs: 3600000, maxRequests: 1000, algorithm: 'fixed' },
371
+ 'per-day': { windowMs: 86400000, maxRequests: 10000, algorithm: 'fixed' }
372
+ };
373
+ return new SlidingWindow(presets[preset]);
374
+ }
375
+ /**
376
+ * Create multiple bucket keys for different scopes from the same identifiers.
377
+ *
378
+ * @param identifiers - Identifiers to use
379
+ * @param prefix - Optional prefix for all keys
380
+ * @returns Object with keys for each scope
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * const keys = createBucketKeys({ agentId: 'a1', userId: 'u1' }, 'rate');
385
+ * // {
386
+ * // global: 'rate:global',
387
+ * // agent: 'rate:agent:a1',
388
+ * // user: 'rate:user:u1',
389
+ * // session: 'rate:session:unknown',
390
+ * // action_type: 'rate:action:unknown'
391
+ * // }
392
+ * ```
393
+ */
394
+ export function createBucketKeys(identifiers, prefix) {
395
+ return {
396
+ global: buildBucketKey('global', identifiers, prefix),
397
+ agent: buildBucketKey('agent', identifiers, prefix),
398
+ session: buildBucketKey('session', identifiers, prefix),
399
+ user: buildBucketKey('user', identifiers, prefix),
400
+ action_type: buildBucketKey('action_type', identifiers, prefix)
401
+ };
402
+ }
403
+ //# sourceMappingURL=rate-limiting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiting.js","sourceRoot":"","sources":["../../src/utils/rate-limiting.ts"],"names":[],"mappings":"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"}