@defai.digital/ax-cli 3.5.2 → 3.6.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 (125) hide show
  1. package/.ax-cli/memory.json +8 -8
  2. package/README.md +27 -1
  3. package/dist/agent/chat-history-manager.d.ts +56 -0
  4. package/dist/agent/chat-history-manager.js +150 -0
  5. package/dist/agent/chat-history-manager.js.map +1 -0
  6. package/dist/agent/llm-agent.js +1 -1
  7. package/dist/agent/llm-agent.js.map +1 -1
  8. package/dist/agent/tool-manager.d.ts +39 -0
  9. package/dist/agent/tool-manager.js +76 -0
  10. package/dist/agent/tool-manager.js.map +1 -0
  11. package/dist/analyzers/ast/index.d.ts +9 -0
  12. package/dist/analyzers/ast/index.js +10 -0
  13. package/dist/analyzers/ast/index.js.map +1 -0
  14. package/dist/analyzers/ast/node-helpers.d.ts +81 -0
  15. package/dist/analyzers/ast/node-helpers.js +128 -0
  16. package/dist/analyzers/ast/node-helpers.js.map +1 -0
  17. package/dist/analyzers/ast/traverser.d.ts +67 -0
  18. package/dist/analyzers/ast/traverser.js +156 -0
  19. package/dist/analyzers/ast/traverser.js.map +1 -0
  20. package/dist/analyzers/best-practices/index.d.ts +10 -0
  21. package/dist/analyzers/best-practices/index.js +11 -0
  22. package/dist/analyzers/best-practices/index.js.map +1 -0
  23. package/dist/commands/setup.js +13 -5
  24. package/dist/commands/setup.js.map +1 -1
  25. package/dist/index.js +7 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/llm/client.d.ts +1 -0
  28. package/dist/llm/client.js +44 -0
  29. package/dist/llm/client.js.map +1 -1
  30. package/dist/mcp/ssrf-protection.d.ts +86 -0
  31. package/dist/mcp/ssrf-protection.js +313 -0
  32. package/dist/mcp/ssrf-protection.js.map +1 -0
  33. package/dist/mcp/validation.d.ts +4 -0
  34. package/dist/mcp/validation.js +122 -11
  35. package/dist/mcp/validation.js.map +1 -1
  36. package/dist/schemas/settings-schemas.d.ts +30 -0
  37. package/dist/schemas/settings-schemas.js +30 -0
  38. package/dist/schemas/settings-schemas.js.map +1 -1
  39. package/dist/tools/bash.d.ts +3 -2
  40. package/dist/tools/bash.js +31 -2
  41. package/dist/tools/bash.js.map +1 -1
  42. package/dist/tools/search.d.ts +1 -1
  43. package/dist/tools/search.js +121 -128
  44. package/dist/tools/search.js.map +1 -1
  45. package/dist/tools/text-editor.js +52 -15
  46. package/dist/tools/text-editor.js.map +1 -1
  47. package/dist/ui/components/status-bar.js +2 -2
  48. package/dist/ui/components/status-bar.js.map +1 -1
  49. package/dist/ui/components/toast-notification.js +0 -1
  50. package/dist/ui/components/toast-notification.js.map +1 -1
  51. package/dist/utils/audit-logger.d.ts +247 -0
  52. package/dist/utils/audit-logger.js +374 -0
  53. package/dist/utils/audit-logger.js.map +1 -0
  54. package/dist/utils/command-security.d.ts +85 -0
  55. package/dist/utils/command-security.js +200 -0
  56. package/dist/utils/command-security.js.map +1 -0
  57. package/dist/utils/encryption.d.ts +78 -0
  58. package/dist/utils/encryption.js +216 -0
  59. package/dist/utils/encryption.js.map +1 -0
  60. package/dist/utils/error-sanitizer.d.ts +119 -0
  61. package/dist/utils/error-sanitizer.js +253 -0
  62. package/dist/utils/error-sanitizer.js.map +1 -0
  63. package/dist/utils/input-sanitizer.d.ts +210 -0
  64. package/dist/utils/input-sanitizer.js +362 -0
  65. package/dist/utils/input-sanitizer.js.map +1 -0
  66. package/dist/utils/json-utils.d.ts +13 -0
  67. package/dist/utils/json-utils.js +55 -1
  68. package/dist/utils/json-utils.js.map +1 -1
  69. package/dist/utils/parallel-analyzer.js +29 -12
  70. package/dist/utils/parallel-analyzer.js.map +1 -1
  71. package/dist/utils/path-security.d.ts +90 -0
  72. package/dist/utils/path-security.js +328 -0
  73. package/dist/utils/path-security.js.map +1 -0
  74. package/dist/utils/process-pool.d.ts +105 -0
  75. package/dist/utils/process-pool.js +326 -0
  76. package/dist/utils/process-pool.js.map +1 -0
  77. package/dist/utils/rate-limiter.d.ts +207 -0
  78. package/dist/utils/rate-limiter.js +303 -0
  79. package/dist/utils/rate-limiter.js.map +1 -0
  80. package/dist/utils/settings-manager.js +83 -4
  81. package/dist/utils/settings-manager.js.map +1 -1
  82. package/eslint.config.js +3 -0
  83. package/package.json +1 -1
  84. package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
  85. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
  86. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
  87. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
  88. package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
  89. package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
  90. package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
  91. package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
  92. package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
  93. package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
  94. package/ax.config.json +0 -333
  95. package/dist/hooks/use-chat-reducer.d.ts +0 -61
  96. package/dist/hooks/use-chat-reducer.js +0 -118
  97. package/dist/hooks/use-chat-reducer.js.map +0 -1
  98. package/dist/hooks/use-enhanced-input.d.ts +0 -40
  99. package/dist/hooks/use-enhanced-input.js +0 -249
  100. package/dist/hooks/use-enhanced-input.js.map +0 -1
  101. package/dist/hooks/use-input-handler.d.ts +0 -46
  102. package/dist/hooks/use-input-handler.js +0 -1430
  103. package/dist/hooks/use-input-handler.js.map +0 -1
  104. package/dist/hooks/use-input-history.d.ts +0 -9
  105. package/dist/hooks/use-input-history.js +0 -112
  106. package/dist/hooks/use-input-history.js.map +0 -1
  107. package/dist/utils/paste-collapse.d.ts +0 -46
  108. package/dist/utils/paste-collapse.js +0 -77
  109. package/dist/utils/paste-collapse.js.map +0 -1
  110. package/packages/schemas/dist/index.d.ts +0 -14
  111. package/packages/schemas/dist/index.d.ts.map +0 -1
  112. package/packages/schemas/dist/index.js +0 -19
  113. package/packages/schemas/dist/index.js.map +0 -1
  114. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  115. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  116. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  117. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  118. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  119. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  120. package/packages/schemas/dist/public/core/enums.js +0 -222
  121. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  122. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  123. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  124. package/packages/schemas/dist/public/core/id-types.js +0 -136
  125. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Process Pool Manager
3
+ *
4
+ * Manages a pool of reusable child processes to prevent memory leaks
5
+ * and resource exhaustion (REQ-ARCH-002).
6
+ *
7
+ * Key features:
8
+ * - Limits concurrent processes to prevent resource exhaustion
9
+ * - Queues requests when pool is full
10
+ * - Automatic cleanup of idle processes
11
+ * - Graceful shutdown with proper cleanup
12
+ * - Memory leak prevention through proper event listener management
13
+ *
14
+ * @module process-pool
15
+ */
16
+ import { spawn } from 'child_process';
17
+ import { EventEmitter } from 'events';
18
+ /**
19
+ * Process pool manager for efficient process reuse
20
+ */
21
+ export class ProcessPool extends EventEmitter {
22
+ maxProcesses;
23
+ processTimeout;
24
+ maxQueueSize;
25
+ activeProcesses = new Set();
26
+ taskQueue = [];
27
+ shuttingDown = false;
28
+ idleTimers = new Map();
29
+ constructor(config = {}) {
30
+ super();
31
+ this.maxProcesses = config.maxProcesses ?? 5;
32
+ this.processTimeout = config.processTimeout ?? 30000;
33
+ this.maxQueueSize = config.maxQueueSize ?? 100;
34
+ }
35
+ /**
36
+ * Execute a command using the process pool
37
+ */
38
+ async execute(options) {
39
+ if (this.shuttingDown) {
40
+ throw new Error('Process pool is shutting down');
41
+ }
42
+ // Check queue size limit
43
+ if (this.taskQueue.length >= this.maxQueueSize) {
44
+ throw new Error(`Process pool queue is full (max: ${this.maxQueueSize})`);
45
+ }
46
+ return new Promise((resolve, reject) => {
47
+ const task = {
48
+ options,
49
+ resolve,
50
+ reject,
51
+ timestamp: Date.now(),
52
+ };
53
+ this.taskQueue.push(task);
54
+ this.processQueue();
55
+ });
56
+ }
57
+ /**
58
+ * Process the task queue
59
+ */
60
+ processQueue() {
61
+ // Don't process if shutting down
62
+ if (this.shuttingDown) {
63
+ return;
64
+ }
65
+ // Process tasks while we have capacity
66
+ while (this.taskQueue.length > 0 &&
67
+ this.activeProcesses.size < this.maxProcesses) {
68
+ const task = this.taskQueue.shift();
69
+ if (!task)
70
+ break;
71
+ this.executeTask(task);
72
+ }
73
+ }
74
+ /**
75
+ * Execute a single task
76
+ */
77
+ async executeTask(task) {
78
+ const { options, resolve, reject } = task;
79
+ try {
80
+ const result = await this.spawnProcess(options);
81
+ resolve(result);
82
+ }
83
+ catch (error) {
84
+ reject(error instanceof Error ? error : new Error(String(error)));
85
+ }
86
+ finally {
87
+ // Process next task in queue
88
+ this.processQueue();
89
+ }
90
+ }
91
+ /**
92
+ * Spawn a process and manage its lifecycle
93
+ */
94
+ async spawnProcess(options) {
95
+ return new Promise((resolve, reject) => {
96
+ const proc = spawn(options.command, options.args, {
97
+ cwd: options.cwd,
98
+ });
99
+ this.activeProcesses.add(proc);
100
+ let stdout = '';
101
+ let stderr = '';
102
+ let isResolved = false;
103
+ let timeoutHandle = null;
104
+ // Set timeout
105
+ const timeout = options.timeout ?? this.processTimeout;
106
+ if (timeout > 0) {
107
+ timeoutHandle = setTimeout(() => {
108
+ if (!isResolved) {
109
+ isResolved = true;
110
+ this.cleanupProcess(proc, timeoutHandle);
111
+ reject(new Error(`Process timeout after ${timeout}ms`));
112
+ }
113
+ }, timeout);
114
+ }
115
+ // Collect stdout
116
+ if (proc.stdout) {
117
+ proc.stdout.on('data', (data) => {
118
+ stdout += data.toString();
119
+ });
120
+ }
121
+ // Collect stderr
122
+ if (proc.stderr) {
123
+ proc.stderr.on('data', (data) => {
124
+ stderr += data.toString();
125
+ });
126
+ }
127
+ // Handle process exit
128
+ proc.on('close', (code, signal) => {
129
+ if (isResolved) {
130
+ return;
131
+ }
132
+ isResolved = true;
133
+ this.cleanupProcess(proc, timeoutHandle);
134
+ resolve({
135
+ stdout,
136
+ stderr,
137
+ exitCode: code,
138
+ signal: signal,
139
+ });
140
+ });
141
+ // Handle process errors
142
+ proc.on('error', (error) => {
143
+ if (isResolved) {
144
+ return;
145
+ }
146
+ isResolved = true;
147
+ this.cleanupProcess(proc, timeoutHandle);
148
+ reject(error);
149
+ });
150
+ });
151
+ }
152
+ /**
153
+ * Cleanup process and associated resources
154
+ */
155
+ cleanupProcess(proc, timeoutHandle) {
156
+ // Clear timeout
157
+ if (timeoutHandle) {
158
+ clearTimeout(timeoutHandle);
159
+ }
160
+ // Clear idle timer if exists
161
+ const idleTimer = this.idleTimers.get(proc);
162
+ if (idleTimer) {
163
+ clearTimeout(idleTimer);
164
+ this.idleTimers.delete(proc);
165
+ }
166
+ // Remove all event listeners to prevent memory leaks
167
+ if (proc.stdout) {
168
+ proc.stdout.removeAllListeners();
169
+ }
170
+ if (proc.stderr) {
171
+ proc.stderr.removeAllListeners();
172
+ }
173
+ proc.removeAllListeners();
174
+ // Kill process if still running
175
+ if (proc.exitCode === null && proc.signalCode === null) {
176
+ try {
177
+ proc.kill('SIGTERM');
178
+ // Force kill after 3 seconds if SIGTERM doesn't work
179
+ const forceKillTimeout = setTimeout(() => {
180
+ try {
181
+ if (proc.exitCode === null && !proc.killed) {
182
+ proc.kill('SIGKILL');
183
+ }
184
+ }
185
+ catch {
186
+ // Process already terminated
187
+ }
188
+ // Always clear timeout to prevent leak
189
+ clearTimeout(forceKillTimeout);
190
+ }, 3000);
191
+ // Clear force kill timeout when process exits
192
+ // NOTE: Use setImmediate to ensure listener fires even if already exited
193
+ setImmediate(() => {
194
+ if (proc.exitCode !== null || proc.signalCode !== null) {
195
+ clearTimeout(forceKillTimeout);
196
+ }
197
+ else {
198
+ proc.once('exit', () => clearTimeout(forceKillTimeout));
199
+ }
200
+ });
201
+ }
202
+ catch {
203
+ // Process already terminated or can't be killed
204
+ }
205
+ }
206
+ // Remove from active set
207
+ this.activeProcesses.delete(proc);
208
+ // Emit metrics event
209
+ this.emit('processCompleted', {
210
+ activeProcesses: this.activeProcesses.size,
211
+ queuedTasks: this.taskQueue.length,
212
+ });
213
+ }
214
+ /**
215
+ * Get pool statistics
216
+ */
217
+ getStats() {
218
+ return {
219
+ activeProcesses: this.activeProcesses.size,
220
+ queuedTasks: this.taskQueue.length,
221
+ maxProcesses: this.maxProcesses,
222
+ maxQueueSize: this.maxQueueSize,
223
+ };
224
+ }
225
+ /**
226
+ * Shutdown the pool gracefully
227
+ */
228
+ async shutdown(force = false) {
229
+ this.shuttingDown = true;
230
+ // Reject all queued tasks
231
+ while (this.taskQueue.length > 0) {
232
+ const task = this.taskQueue.shift();
233
+ if (task) {
234
+ task.reject(new Error('Process pool shutting down'));
235
+ }
236
+ }
237
+ // Wait for active processes to complete or force kill
238
+ if (force) {
239
+ // Force kill all active processes
240
+ for (const proc of this.activeProcesses) {
241
+ try {
242
+ proc.kill('SIGKILL');
243
+ }
244
+ catch {
245
+ // Ignore errors
246
+ }
247
+ }
248
+ this.activeProcesses.clear();
249
+ }
250
+ else {
251
+ // Wait for active processes to complete (with timeout)
252
+ const shutdownTimeout = 10000; // 10 seconds
253
+ const startTime = Date.now();
254
+ while (this.activeProcesses.size > 0) {
255
+ if (Date.now() - startTime > shutdownTimeout) {
256
+ // Force kill remaining processes
257
+ for (const proc of this.activeProcesses) {
258
+ try {
259
+ proc.kill('SIGKILL');
260
+ }
261
+ catch {
262
+ // Ignore errors
263
+ }
264
+ }
265
+ this.activeProcesses.clear();
266
+ break;
267
+ }
268
+ // Wait 100ms before checking again
269
+ await new Promise((resolve) => setTimeout(resolve, 100));
270
+ }
271
+ }
272
+ // Clear all idle timers
273
+ for (const timer of this.idleTimers.values()) {
274
+ clearTimeout(timer);
275
+ }
276
+ this.idleTimers.clear();
277
+ this.emit('shutdown');
278
+ }
279
+ /**
280
+ * Check if pool is idle (no active processes or queued tasks)
281
+ */
282
+ isIdle() {
283
+ return this.activeProcesses.size === 0 && this.taskQueue.length === 0;
284
+ }
285
+ /**
286
+ * Check if pool is at capacity
287
+ */
288
+ isAtCapacity() {
289
+ return this.activeProcesses.size >= this.maxProcesses;
290
+ }
291
+ }
292
+ /**
293
+ * Singleton process pool instance for ripgrep
294
+ */
295
+ let ripgrepPool = null;
296
+ /**
297
+ * Get or create the ripgrep process pool
298
+ */
299
+ export function getRipgrepPool() {
300
+ if (!ripgrepPool) {
301
+ ripgrepPool = new ProcessPool({
302
+ maxProcesses: 5,
303
+ processTimeout: 30000,
304
+ maxQueueSize: 100,
305
+ });
306
+ // Cleanup on process exit
307
+ process.on('beforeExit', () => {
308
+ if (ripgrepPool) {
309
+ ripgrepPool.shutdown(true).catch(() => {
310
+ // Ignore errors during shutdown
311
+ });
312
+ }
313
+ });
314
+ }
315
+ return ripgrepPool;
316
+ }
317
+ /**
318
+ * Shutdown the ripgrep pool (for testing)
319
+ */
320
+ export async function shutdownRipgrepPool() {
321
+ if (ripgrepPool) {
322
+ await ripgrepPool.shutdown();
323
+ ripgrepPool = null;
324
+ }
325
+ }
326
+ //# sourceMappingURL=process-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-pool.js","sourceRoot":"","sources":["../../src/utils/process-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Rate Limiting Utilities (REQ-SEC-006)
3
+ *
4
+ * Implements token bucket algorithm for rate limiting API calls and user actions
5
+ * Prevents API abuse and ensures fair resource usage
6
+ *
7
+ * Security: Protects against:
8
+ * - API abuse (excessive requests)
9
+ * - Resource exhaustion
10
+ * - Denial of service (unintentional)
11
+ */
12
+ export interface RateLimitConfig {
13
+ /**
14
+ * Maximum number of requests allowed in the window
15
+ */
16
+ maxRequests: number;
17
+ /**
18
+ * Time window in milliseconds
19
+ */
20
+ windowMs: number;
21
+ /**
22
+ * Optional: burst allowance (can exceed limit briefly)
23
+ */
24
+ burstAllowance?: number;
25
+ }
26
+ export interface RateLimitResult {
27
+ /**
28
+ * Whether the request is allowed
29
+ */
30
+ allowed: boolean;
31
+ /**
32
+ * Tokens remaining in the current window
33
+ */
34
+ remaining: number;
35
+ /**
36
+ * Time until the rate limit resets (in milliseconds)
37
+ */
38
+ resetIn: number;
39
+ /**
40
+ * Total limit for this rate limiter
41
+ */
42
+ limit: number;
43
+ }
44
+ /**
45
+ * Token Bucket Rate Limiter
46
+ *
47
+ * Uses the token bucket algorithm which allows bursts while maintaining
48
+ * a steady average rate. Tokens are added at a constant rate, and requests
49
+ * consume tokens.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const limiter = new RateLimiter({
54
+ * maxRequests: 60,
55
+ * windowMs: 60000, // 60 requests per minute
56
+ * });
57
+ *
58
+ * const result = limiter.tryAcquire();
59
+ * if (result.allowed) {
60
+ * // Make API call
61
+ * } else {
62
+ * console.log(`Rate limit exceeded. Try again in ${result.resetIn}ms`);
63
+ * }
64
+ * ```
65
+ */
66
+ export declare class RateLimiter {
67
+ private tokens;
68
+ private readonly maxTokens;
69
+ private readonly refillRate;
70
+ private lastRefill;
71
+ private readonly config;
72
+ constructor(config: RateLimitConfig);
73
+ /**
74
+ * Refill tokens based on elapsed time
75
+ */
76
+ private refill;
77
+ /**
78
+ * Try to acquire a token (allow a request)
79
+ *
80
+ * @param cost - Number of tokens to consume (default: 1)
81
+ * @returns Rate limit result indicating if request is allowed
82
+ */
83
+ tryAcquire(cost?: number): RateLimitResult;
84
+ /**
85
+ * Get current state without consuming a token
86
+ */
87
+ getState(): RateLimitResult;
88
+ /**
89
+ * Reset the rate limiter (clear all tokens)
90
+ */
91
+ reset(): void;
92
+ }
93
+ /**
94
+ * Multi-tier Rate Limiter
95
+ *
96
+ * Enforces multiple rate limits simultaneously (e.g., per-second, per-minute, per-hour)
97
+ * Request is only allowed if ALL tiers allow it
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const limiter = new MultiTierRateLimiter([
102
+ * { maxRequests: 10, windowMs: 1000 }, // 10/second
103
+ * { maxRequests: 100, windowMs: 60000 }, // 100/minute
104
+ * ]);
105
+ * ```
106
+ */
107
+ export declare class MultiTierRateLimiter {
108
+ private limiters;
109
+ constructor(configs: RateLimitConfig[]);
110
+ /**
111
+ * Try to acquire across all tiers
112
+ * Request is only allowed if ALL tiers allow it
113
+ */
114
+ tryAcquire(cost?: number): RateLimitResult;
115
+ /**
116
+ * Get current state (most restrictive tier)
117
+ */
118
+ getState(): RateLimitResult;
119
+ /**
120
+ * Reset all tiers
121
+ */
122
+ reset(): void;
123
+ }
124
+ /**
125
+ * Keyed Rate Limiter
126
+ *
127
+ * Maintains separate rate limits for different keys (e.g., per-user, per-IP)
128
+ * Automatically cleans up old entries to prevent memory leaks
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const limiter = new KeyedRateLimiter({
133
+ * maxRequests: 100,
134
+ * windowMs: 60000,
135
+ * });
136
+ *
137
+ * // Different limits for different users
138
+ * const result = limiter.tryAcquire('user-123');
139
+ * ```
140
+ */
141
+ export declare class KeyedRateLimiter {
142
+ private limiters;
143
+ private readonly config;
144
+ private cleanupTimer;
145
+ private readonly maxKeys;
146
+ constructor(config: RateLimitConfig, maxKeys?: number);
147
+ /**
148
+ * Get or create a rate limiter for the given key
149
+ */
150
+ private getLimiter;
151
+ /**
152
+ * Try to acquire for a specific key
153
+ */
154
+ tryAcquire(key: string, cost?: number): RateLimitResult;
155
+ /**
156
+ * Get state for a specific key
157
+ */
158
+ getState(key: string): RateLimitResult;
159
+ /**
160
+ * Reset a specific key
161
+ */
162
+ reset(key: string): void;
163
+ /**
164
+ * Clean up inactive limiters
165
+ */
166
+ private cleanup;
167
+ /**
168
+ * Dispose of resources
169
+ */
170
+ dispose(): void;
171
+ }
172
+ /**
173
+ * Default rate limit configurations for common use cases
174
+ */
175
+ export declare const DEFAULT_RATE_LIMITS: {
176
+ /**
177
+ * API calls - 60 requests per minute
178
+ */
179
+ readonly API: {
180
+ readonly maxRequests: 60;
181
+ readonly windowMs: number;
182
+ readonly burstAllowance: 10;
183
+ };
184
+ /**
185
+ * LLM API calls - 20 requests per minute (more expensive)
186
+ */
187
+ readonly LLM_API: {
188
+ readonly maxRequests: 20;
189
+ readonly windowMs: number;
190
+ readonly burstAllowance: 5;
191
+ };
192
+ /**
193
+ * User actions - 100 requests per minute
194
+ */
195
+ readonly USER_ACTIONS: {
196
+ readonly maxRequests: 100;
197
+ readonly windowMs: number;
198
+ readonly burstAllowance: 20;
199
+ };
200
+ /**
201
+ * File operations - 50 per minute
202
+ */
203
+ readonly FILE_OPS: {
204
+ readonly maxRequests: 50;
205
+ readonly windowMs: number;
206
+ };
207
+ };