@marktoflow/integrations 2.0.4-alpha.1 → 2.0.4

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 (82) hide show
  1. package/README.md +2 -2
  2. package/dist/adapters/claude-code.d.ts +34 -0
  3. package/dist/adapters/claude-code.d.ts.map +1 -0
  4. package/dist/adapters/claude-code.js +89 -0
  5. package/dist/adapters/claude-code.js.map +1 -0
  6. package/dist/adapters/github-copilot-types.d.ts +2 -2
  7. package/dist/adapters/github-copilot-workflow.d.ts +2 -2
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -4
  11. package/dist/index.js.map +1 -1
  12. package/dist/reliability/index.d.ts +1 -3
  13. package/dist/reliability/index.d.ts.map +1 -1
  14. package/dist/reliability/index.js +1 -3
  15. package/dist/reliability/index.js.map +1 -1
  16. package/dist/reliability/wrapper.d.ts +0 -9
  17. package/dist/reliability/wrapper.d.ts.map +1 -1
  18. package/dist/reliability/wrapper.js +12 -62
  19. package/dist/reliability/wrapper.js.map +1 -1
  20. package/dist/services/base-client.d.ts.map +1 -1
  21. package/dist/services/base-client.js +3 -25
  22. package/dist/services/base-client.js.map +1 -1
  23. package/dist/services/discord.d.ts.map +1 -1
  24. package/dist/services/discord.js +0 -6
  25. package/dist/services/discord.js.map +1 -1
  26. package/dist/services/gmail.d.ts.map +1 -1
  27. package/dist/services/gmail.js +47 -65
  28. package/dist/services/gmail.js.map +1 -1
  29. package/dist/services/google-calendar.js +5 -9
  30. package/dist/services/google-calendar.js.map +1 -1
  31. package/dist/services/google-docs.js +5 -9
  32. package/dist/services/google-docs.js.map +1 -1
  33. package/dist/services/google-drive.js +5 -9
  34. package/dist/services/google-drive.js.map +1 -1
  35. package/dist/services/google-sheets.js +5 -9
  36. package/dist/services/google-sheets.js.map +1 -1
  37. package/dist/services/http.d.ts.map +1 -1
  38. package/dist/services/http.js +1 -15
  39. package/dist/services/http.js.map +1 -1
  40. package/dist/services/mailchimp.d.ts.map +1 -1
  41. package/dist/services/mailchimp.js +0 -3
  42. package/dist/services/mailchimp.js.map +1 -1
  43. package/dist/services/outlook.d.ts.map +1 -1
  44. package/dist/services/outlook.js +11 -14
  45. package/dist/services/outlook.js.map +1 -1
  46. package/dist/services/shopify.d.ts.map +1 -1
  47. package/dist/services/shopify.js +0 -3
  48. package/dist/services/shopify.js.map +1 -1
  49. package/dist/services/trello.d.ts.map +1 -1
  50. package/dist/services/trello.js +1 -7
  51. package/dist/services/trello.js.map +1 -1
  52. package/package.json +3 -6
  53. package/dist/adapters/claude-agent-hooks.d.ts +0 -176
  54. package/dist/reliability/circuit-breaker.d.ts +0 -67
  55. package/dist/reliability/circuit-breaker.d.ts.map +0 -1
  56. package/dist/reliability/circuit-breaker.js +0 -164
  57. package/dist/reliability/circuit-breaker.js.map +0 -1
  58. package/dist/reliability/rate-limiter.d.ts +0 -62
  59. package/dist/reliability/rate-limiter.d.ts.map +0 -1
  60. package/dist/reliability/rate-limiter.js +0 -194
  61. package/dist/reliability/rate-limiter.js.map +0 -1
  62. package/dist/services/github.d.ts +0 -3
  63. package/dist/services/gmail-trigger.d.ts +0 -92
  64. package/dist/services/gmail.d.ts +0 -116
  65. package/dist/services/google-calendar.d.ts +0 -220
  66. package/dist/services/google-docs.d.ts +0 -197
  67. package/dist/services/google-drive.d.ts +0 -149
  68. package/dist/services/google-sheets.d.ts +0 -165
  69. package/dist/services/http.d.ts +0 -120
  70. package/dist/services/jira.d.ts +0 -3
  71. package/dist/services/linear.d.ts +0 -163
  72. package/dist/services/mysql.d.ts +0 -91
  73. package/dist/services/outlook-trigger.d.ts +0 -121
  74. package/dist/services/outlook.d.ts +0 -237
  75. package/dist/services/postgres.d.ts +0 -83
  76. package/dist/services/rss.d.ts +0 -57
  77. package/dist/services/rss.d.ts.map +0 -1
  78. package/dist/services/rss.js +0 -190
  79. package/dist/services/rss.js.map +0 -1
  80. package/dist/services/slack-socket.d.ts +0 -18
  81. package/dist/services/slack.d.ts +0 -3
  82. package/dist/services/whatsapp.d.ts +0 -311
@@ -1,176 +0,0 @@
1
- /**
2
- * Claude Agent SDK Hooks for marktoflow
3
- *
4
- * Provides pre-built hook configurations for common use cases:
5
- * - Audit logging
6
- * - Cost tracking
7
- * - Approval workflows
8
- * - File change monitoring
9
- * - Security enforcement
10
- */
11
- import { HookCallback, HookEvent, ToolPermissionHandler } from './claude-agent-types.js';
12
- /**
13
- * Audit log entry
14
- */
15
- export interface AuditLogEntry {
16
- timestamp: Date;
17
- event: HookEvent;
18
- toolName?: string;
19
- toolInput?: Record<string, unknown>;
20
- toolResponse?: string;
21
- sessionId?: string;
22
- error?: string;
23
- duration?: number;
24
- metadata?: Record<string, unknown>;
25
- }
26
- /**
27
- * Audit logger interface
28
- */
29
- export interface AuditLogger {
30
- log(entry: AuditLogEntry): Promise<void>;
31
- flush(): Promise<void>;
32
- }
33
- /**
34
- * Console audit logger (default)
35
- */
36
- export declare class ConsoleAuditLogger implements AuditLogger {
37
- private prefix;
38
- constructor(prefix?: string);
39
- log(entry: AuditLogEntry): Promise<void>;
40
- flush(): Promise<void>;
41
- }
42
- /**
43
- * File audit logger
44
- */
45
- export declare class FileAuditLogger implements AuditLogger {
46
- private filePath;
47
- private buffer;
48
- private bufferSize;
49
- constructor(filePath: string, bufferSize?: number);
50
- log(entry: AuditLogEntry): Promise<void>;
51
- flush(): Promise<void>;
52
- }
53
- /**
54
- * Create audit logging hooks
55
- */
56
- export declare function createAuditHooks(logger?: AuditLogger): Partial<Record<HookEvent, HookCallback[]>>;
57
- /**
58
- * Cost tracker for monitoring spending
59
- */
60
- export interface CostTracker {
61
- /** Current total cost in USD */
62
- totalCostUsd: number;
63
- /** Cost per model */
64
- costByModel: Record<string, number>;
65
- /** Tool execution counts */
66
- toolCounts: Record<string, number>;
67
- /** Start time */
68
- startTime: Date;
69
- /** Number of API calls */
70
- apiCalls: number;
71
- }
72
- /**
73
- * Cost tracking callback
74
- */
75
- export type CostCallback = (tracker: CostTracker) => void | Promise<void>;
76
- /**
77
- * Create a cost tracker
78
- */
79
- export declare function createCostTracker(): CostTracker;
80
- /**
81
- * Create cost tracking hooks
82
- */
83
- export declare function createCostTrackingHooks(tracker: CostTracker, callbacks?: {
84
- onToolUse?: CostCallback;
85
- onBudgetWarning?: CostCallback;
86
- budgetWarningThreshold?: number;
87
- }): Partial<Record<HookEvent, HookCallback[]>>;
88
- /**
89
- * Approval request
90
- */
91
- export interface ApprovalRequest {
92
- toolName: string;
93
- toolInput: Record<string, unknown>;
94
- reason?: string;
95
- }
96
- /**
97
- * Approval handler
98
- */
99
- export type ApprovalHandler = (request: ApprovalRequest) => Promise<boolean>;
100
- /**
101
- * Create approval workflow hooks
102
- */
103
- export declare function createApprovalHooks(approvalHandler: ApprovalHandler, toolsRequiringApproval?: string[]): Partial<Record<HookEvent, HookCallback[]>>;
104
- /**
105
- * File change record
106
- */
107
- export interface FileChange {
108
- timestamp: Date;
109
- operation: 'read' | 'write' | 'edit';
110
- filePath: string;
111
- toolInput?: Record<string, unknown>;
112
- }
113
- /**
114
- * File change callback
115
- */
116
- export type FileChangeCallback = (change: FileChange) => void | Promise<void>;
117
- /**
118
- * Create file monitoring hooks
119
- */
120
- export declare function createFileMonitoringHooks(callback: FileChangeCallback): Partial<Record<HookEvent, HookCallback[]>>;
121
- /**
122
- * Security policy for tool execution
123
- */
124
- export interface SecurityPolicy {
125
- /** Blocked file patterns (glob) */
126
- blockedPaths?: string[];
127
- /** Blocked commands (regex) */
128
- blockedCommands?: string[];
129
- /** Allowed working directories */
130
- allowedDirectories?: string[];
131
- /** Maximum file size for writes (bytes) */
132
- maxFileSize?: number;
133
- /** Block network access */
134
- blockNetwork?: boolean;
135
- }
136
- /**
137
- * Create a security-enforcing permission handler
138
- */
139
- export declare function createSecurityPermissionHandler(policy: SecurityPolicy): ToolPermissionHandler;
140
- /**
141
- * Preset hook configurations for common use cases
142
- */
143
- export declare const PresetHooks: {
144
- /**
145
- * Development mode - permissive with logging
146
- */
147
- development: (logger?: AuditLogger) => {
148
- PreToolUse?: HookCallback[] | undefined;
149
- PostToolUse?: HookCallback[] | undefined;
150
- PostToolUseFailure?: HookCallback[] | undefined;
151
- PermissionRequest?: HookCallback[] | undefined;
152
- SessionStart?: HookCallback[] | undefined;
153
- SessionEnd?: HookCallback[] | undefined;
154
- Stop?: HookCallback[] | undefined;
155
- };
156
- /**
157
- * Production mode - strict with approval and monitoring
158
- */
159
- production: (approvalHandler: ApprovalHandler, logger?: AuditLogger) => Partial<Record<HookEvent, HookCallback[]>>;
160
- /**
161
- * CI/CD mode - automated with cost tracking
162
- */
163
- cicd: (costTracker: CostTracker, maxBudget?: number) => Partial<Record<HookEvent, HookCallback[]>>;
164
- /**
165
- * Secure mode - strict security with file monitoring
166
- */
167
- secure: (policy: SecurityPolicy, fileChangeCallback?: FileChangeCallback) => {
168
- hooks: Partial<Record<HookEvent, HookCallback[]>>;
169
- canUseTool: ToolPermissionHandler;
170
- };
171
- };
172
- /**
173
- * Merge multiple hook configurations
174
- */
175
- export declare function mergeHooks(...hookConfigs: Array<Partial<Record<HookEvent, HookCallback[]>>>): Partial<Record<HookEvent, HookCallback[]>>;
176
- //# sourceMappingURL=claude-agent-hooks.d.ts.map
@@ -1,67 +0,0 @@
1
- /**
2
- * Circuit Breaker for integration reliability.
3
- *
4
- * Prevents cascading failures by tracking error rates per service
5
- * and short-circuiting requests when a service is unhealthy.
6
- *
7
- * States:
8
- * - CLOSED: Normal operation, requests pass through
9
- * - OPEN: Service is failing, requests are rejected immediately
10
- * - HALF_OPEN: Testing if service has recovered (limited requests allowed)
11
- */
12
- export type CircuitState = 'closed' | 'open' | 'half_open';
13
- export interface CircuitBreakerOptions {
14
- /** Number of failures before opening circuit (default: 5) */
15
- failureThreshold?: number;
16
- /** Time in ms before attempting recovery (default: 30000) */
17
- resetTimeout?: number;
18
- /** Number of successful requests in half-open to close circuit (default: 2) */
19
- successThreshold?: number;
20
- /** Time window in ms for counting failures (default: 60000) */
21
- failureWindow?: number;
22
- /** Called when circuit state changes */
23
- onStateChange?: (service: string, from: CircuitState, to: CircuitState) => void;
24
- }
25
- export declare class CircuitBreakerRegistry {
26
- private circuits;
27
- private options;
28
- private onStateChange?;
29
- constructor(options?: CircuitBreakerOptions);
30
- /**
31
- * Check if a request to the given service should be allowed.
32
- * Throws immediately if circuit is open.
33
- */
34
- allowRequest(service: string): void;
35
- /**
36
- * Record a successful request.
37
- */
38
- recordSuccess(service: string): void;
39
- /**
40
- * Record a failed request.
41
- */
42
- recordFailure(service: string): void;
43
- /**
44
- * Get current state of a service's circuit.
45
- */
46
- getState(service: string): CircuitState;
47
- /**
48
- * Get stats for all circuits.
49
- */
50
- getStats(): Record<string, {
51
- state: CircuitState;
52
- recentFailures: number;
53
- }>;
54
- /**
55
- * Reset a specific service's circuit to closed.
56
- */
57
- reset(service: string): void;
58
- /**
59
- * Reset all circuits.
60
- */
61
- resetAll(): void;
62
- private getCircuit;
63
- private transition;
64
- }
65
- export declare function getCircuitBreakerRegistry(options?: CircuitBreakerOptions): CircuitBreakerRegistry;
66
- export declare function resetCircuitBreakerRegistry(): void;
67
- //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/reliability/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,KAAK,IAAI,CAAC;CACjF;AAiBD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,OAAO,CAAyD;IACxE,OAAO,CAAC,aAAa,CAAC,CAAyC;gBAEnD,OAAO,GAAE,qBAA0B;IAU/C;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IA4BnC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAWpC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAsBpC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAIvC;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IAc3E;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,UAAU;CAgBnB;AAKD,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,sBAAsB,CAKjG;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD"}
@@ -1,164 +0,0 @@
1
- /**
2
- * Circuit Breaker for integration reliability.
3
- *
4
- * Prevents cascading failures by tracking error rates per service
5
- * and short-circuiting requests when a service is unhealthy.
6
- *
7
- * States:
8
- * - CLOSED: Normal operation, requests pass through
9
- * - OPEN: Service is failing, requests are rejected immediately
10
- * - HALF_OPEN: Testing if service has recovered (limited requests allowed)
11
- */
12
- import { IntegrationRequestError } from './errors.js';
13
- const DEFAULT_OPTIONS = {
14
- failureThreshold: 5,
15
- resetTimeout: 30_000,
16
- successThreshold: 2,
17
- failureWindow: 60_000,
18
- };
19
- export class CircuitBreakerRegistry {
20
- circuits = new Map();
21
- options;
22
- onStateChange;
23
- constructor(options = {}) {
24
- this.options = {
25
- failureThreshold: options.failureThreshold ?? DEFAULT_OPTIONS.failureThreshold,
26
- resetTimeout: options.resetTimeout ?? DEFAULT_OPTIONS.resetTimeout,
27
- successThreshold: options.successThreshold ?? DEFAULT_OPTIONS.successThreshold,
28
- failureWindow: options.failureWindow ?? DEFAULT_OPTIONS.failureWindow,
29
- };
30
- this.onStateChange = options.onStateChange;
31
- }
32
- /**
33
- * Check if a request to the given service should be allowed.
34
- * Throws immediately if circuit is open.
35
- */
36
- allowRequest(service) {
37
- const circuit = this.getCircuit(service);
38
- const now = Date.now();
39
- switch (circuit.state) {
40
- case 'closed':
41
- return; // Allow
42
- case 'open': {
43
- // Check if reset timeout has elapsed
44
- if (now - circuit.openedAt >= this.options.resetTimeout) {
45
- this.transition(service, circuit, 'half_open');
46
- return; // Allow probe request
47
- }
48
- throw new IntegrationRequestError({
49
- service,
50
- action: 'circuit_breaker',
51
- message: `Circuit breaker is open for ${service} — too many recent failures. Retry after ${Math.ceil((circuit.openedAt + this.options.resetTimeout - now) / 1000)}s`,
52
- retryable: true,
53
- retryAfter: Math.ceil((circuit.openedAt + this.options.resetTimeout - now) / 1000),
54
- });
55
- }
56
- case 'half_open':
57
- return; // Allow probe request
58
- }
59
- }
60
- /**
61
- * Record a successful request.
62
- */
63
- recordSuccess(service) {
64
- const circuit = this.getCircuit(service);
65
- if (circuit.state === 'half_open') {
66
- circuit.successes++;
67
- if (circuit.successes >= this.options.successThreshold) {
68
- this.transition(service, circuit, 'closed');
69
- }
70
- }
71
- }
72
- /**
73
- * Record a failed request.
74
- */
75
- recordFailure(service) {
76
- const circuit = this.getCircuit(service);
77
- const now = Date.now();
78
- if (circuit.state === 'half_open') {
79
- // Any failure in half-open reopens the circuit
80
- this.transition(service, circuit, 'open');
81
- return;
82
- }
83
- // Add failure timestamp and prune old ones
84
- circuit.failures.push(now);
85
- circuit.failures = circuit.failures.filter((t) => now - t < this.options.failureWindow);
86
- circuit.lastFailureAt = now;
87
- if (circuit.failures.length >= this.options.failureThreshold) {
88
- this.transition(service, circuit, 'open');
89
- }
90
- }
91
- /**
92
- * Get current state of a service's circuit.
93
- */
94
- getState(service) {
95
- return this.getCircuit(service).state;
96
- }
97
- /**
98
- * Get stats for all circuits.
99
- */
100
- getStats() {
101
- const stats = {};
102
- const now = Date.now();
103
- for (const [service, circuit] of this.circuits) {
104
- const recentFailures = circuit.failures.filter((t) => now - t < this.options.failureWindow).length;
105
- stats[service] = { state: circuit.state, recentFailures };
106
- }
107
- return stats;
108
- }
109
- /**
110
- * Reset a specific service's circuit to closed.
111
- */
112
- reset(service) {
113
- this.circuits.delete(service);
114
- }
115
- /**
116
- * Reset all circuits.
117
- */
118
- resetAll() {
119
- this.circuits.clear();
120
- }
121
- getCircuit(service) {
122
- let circuit = this.circuits.get(service);
123
- if (!circuit) {
124
- circuit = {
125
- state: 'closed',
126
- failures: [],
127
- successes: 0,
128
- lastFailureAt: 0,
129
- openedAt: 0,
130
- };
131
- this.circuits.set(service, circuit);
132
- }
133
- return circuit;
134
- }
135
- transition(service, circuit, to) {
136
- const from = circuit.state;
137
- circuit.state = to;
138
- if (to === 'open') {
139
- circuit.openedAt = Date.now();
140
- circuit.successes = 0;
141
- }
142
- else if (to === 'closed') {
143
- circuit.failures = [];
144
- circuit.successes = 0;
145
- }
146
- else if (to === 'half_open') {
147
- circuit.successes = 0;
148
- }
149
- this.onStateChange?.(service, from, to);
150
- }
151
- }
152
- /** Global circuit breaker registry shared across all integrations */
153
- let _globalRegistry;
154
- export function getCircuitBreakerRegistry(options) {
155
- if (!_globalRegistry) {
156
- _globalRegistry = new CircuitBreakerRegistry(options);
157
- }
158
- return _globalRegistry;
159
- }
160
- export function resetCircuitBreakerRegistry() {
161
- _globalRegistry?.resetAll();
162
- _globalRegistry = undefined;
163
- }
164
- //# sourceMappingURL=circuit-breaker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/reliability/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -1,62 +0,0 @@
1
- /**
2
- * Proactive rate limiter for integration reliability.
3
- *
4
- * Prevents 429 errors by tracking request rates per service
5
- * and queuing/delaying requests that would exceed known limits.
6
- *
7
- * Uses a token bucket algorithm with configurable refill rates.
8
- */
9
- export interface RateLimitConfig {
10
- /** Maximum requests per window */
11
- maxRequests: number;
12
- /** Window duration in ms */
13
- windowMs: number;
14
- /** Strategy when limit is reached: 'queue' waits, 'reject' throws (default: 'queue') */
15
- strategy?: 'queue' | 'reject';
16
- /** Maximum queue size before rejecting (default: 100) */
17
- maxQueueSize?: number;
18
- }
19
- /** Well-known rate limits for popular services */
20
- export declare const KNOWN_RATE_LIMITS: Record<string, RateLimitConfig>;
21
- export declare class RateLimiterRegistry {
22
- private buckets;
23
- private configs;
24
- private timers;
25
- constructor(overrides?: Record<string, RateLimitConfig>);
26
- /**
27
- * Configure rate limit for a specific service.
28
- */
29
- configure(service: string, config: RateLimitConfig): void;
30
- /**
31
- * Acquire a token for the given service.
32
- * Resolves immediately if tokens available, queues or rejects otherwise.
33
- */
34
- acquire(service: string): Promise<void>;
35
- /**
36
- * Release a token (optional — for manual flow control).
37
- */
38
- release(service: string): void;
39
- /**
40
- * Get current rate limit status for a service.
41
- */
42
- getStatus(service: string): {
43
- available: number;
44
- max: number;
45
- queued: number;
46
- refillRate: number;
47
- } | null;
48
- /**
49
- * Update limits based on response headers (Retry-After, X-RateLimit-*).
50
- */
51
- updateFromHeaders(service: string, headers: Record<string, string>): void;
52
- /**
53
- * Clean up timers.
54
- */
55
- destroy(): void;
56
- private refill;
57
- private drainQueue;
58
- private ensureDrainTimer;
59
- }
60
- export declare function getRateLimiterRegistry(overrides?: Record<string, RateLimitConfig>): RateLimiterRegistry;
61
- export declare function resetRateLimiterRegistry(): void;
62
- //# sourceMappingURL=rate-limiter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/reliability/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,kDAAkD;AAClD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAW7D,CAAC;AAUF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,OAAO,CAAgD;IAC/D,OAAO,CAAC,MAAM,CAAqD;gBAEvD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAYvD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IAmBzD;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC7C;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI;IAYR;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAazE;;OAEG;IACH,OAAO,IAAI,IAAI;IAef,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,gBAAgB;CAiBzB;AAKD,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,mBAAmB,CAKvG;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C"}
@@ -1,194 +0,0 @@
1
- /**
2
- * Proactive rate limiter for integration reliability.
3
- *
4
- * Prevents 429 errors by tracking request rates per service
5
- * and queuing/delaying requests that would exceed known limits.
6
- *
7
- * Uses a token bucket algorithm with configurable refill rates.
8
- */
9
- import { IntegrationRequestError } from './errors.js';
10
- /** Well-known rate limits for popular services */
11
- export const KNOWN_RATE_LIMITS = {
12
- slack: { maxRequests: 50, windowMs: 60_000 },
13
- github: { maxRequests: 5000, windowMs: 3_600_000 },
14
- gmail: { maxRequests: 250, windowMs: 1_000 },
15
- discord: { maxRequests: 50, windowMs: 1_000 },
16
- notion: { maxRequests: 3, windowMs: 1_000 },
17
- linear: { maxRequests: 50, windowMs: 60_000 },
18
- stripe: { maxRequests: 100, windowMs: 1_000 },
19
- sendgrid: { maxRequests: 600, windowMs: 60_000 },
20
- trello: { maxRequests: 100, windowMs: 10_000 },
21
- shopify: { maxRequests: 40, windowMs: 1_000 },
22
- };
23
- export class RateLimiterRegistry {
24
- buckets = new Map();
25
- configs = new Map();
26
- timers = new Map();
27
- constructor(overrides) {
28
- // Load known defaults, allow overrides
29
- for (const [service, config] of Object.entries(KNOWN_RATE_LIMITS)) {
30
- this.configure(service, config);
31
- }
32
- if (overrides) {
33
- for (const [service, config] of Object.entries(overrides)) {
34
- this.configure(service, config);
35
- }
36
- }
37
- }
38
- /**
39
- * Configure rate limit for a specific service.
40
- */
41
- configure(service, config) {
42
- const full = {
43
- maxRequests: config.maxRequests,
44
- windowMs: config.windowMs,
45
- strategy: config.strategy ?? 'queue',
46
- maxQueueSize: config.maxQueueSize ?? 100,
47
- };
48
- this.configs.set(service, full);
49
- const refillRate = config.maxRequests / config.windowMs;
50
- this.buckets.set(service, {
51
- tokens: config.maxRequests,
52
- maxTokens: config.maxRequests,
53
- refillRate,
54
- lastRefillAt: Date.now(),
55
- queue: [],
56
- });
57
- }
58
- /**
59
- * Acquire a token for the given service.
60
- * Resolves immediately if tokens available, queues or rejects otherwise.
61
- */
62
- async acquire(service) {
63
- const bucket = this.buckets.get(service);
64
- if (!bucket)
65
- return; // No rate limit configured — allow
66
- this.refill(bucket);
67
- if (bucket.tokens >= 1) {
68
- bucket.tokens -= 1;
69
- return;
70
- }
71
- const config = this.configs.get(service);
72
- if (config.strategy === 'reject') {
73
- throw new IntegrationRequestError({
74
- service,
75
- action: 'rate_limiter',
76
- message: `Rate limit reached for ${service} (${config.maxRequests} requests per ${config.windowMs}ms)`,
77
- retryable: true,
78
- retryAfter: Math.ceil((1 / bucket.refillRate) / 1000),
79
- });
80
- }
81
- // Queue strategy — wait for a token
82
- if (bucket.queue.length >= config.maxQueueSize) {
83
- throw new IntegrationRequestError({
84
- service,
85
- action: 'rate_limiter',
86
- message: `Rate limit queue full for ${service} (${config.maxQueueSize} pending requests)`,
87
- retryable: true,
88
- });
89
- }
90
- return new Promise((resolve, reject) => {
91
- bucket.queue.push({ resolve, reject });
92
- this.ensureDrainTimer(service, bucket);
93
- });
94
- }
95
- /**
96
- * Release a token (optional — for manual flow control).
97
- */
98
- release(service) {
99
- const bucket = this.buckets.get(service);
100
- if (!bucket)
101
- return;
102
- bucket.tokens = Math.min(bucket.tokens + 1, bucket.maxTokens);
103
- this.drainQueue(bucket);
104
- }
105
- /**
106
- * Get current rate limit status for a service.
107
- */
108
- getStatus(service) {
109
- const bucket = this.buckets.get(service);
110
- if (!bucket)
111
- return null;
112
- this.refill(bucket);
113
- return {
114
- available: Math.floor(bucket.tokens),
115
- max: bucket.maxTokens,
116
- queued: bucket.queue.length,
117
- refillRate: bucket.refillRate * 1000, // tokens per second
118
- };
119
- }
120
- /**
121
- * Update limits based on response headers (Retry-After, X-RateLimit-*).
122
- */
123
- updateFromHeaders(service, headers) {
124
- const remaining = headers['x-ratelimit-remaining'] ?? headers['X-RateLimit-Remaining'];
125
- if (remaining !== undefined) {
126
- const bucket = this.buckets.get(service);
127
- if (bucket) {
128
- const count = parseInt(remaining, 10);
129
- if (!isNaN(count)) {
130
- bucket.tokens = Math.min(count, bucket.maxTokens);
131
- }
132
- }
133
- }
134
- }
135
- /**
136
- * Clean up timers.
137
- */
138
- destroy() {
139
- for (const timer of this.timers.values()) {
140
- clearInterval(timer);
141
- }
142
- this.timers.clear();
143
- // Reject all queued requests
144
- for (const bucket of this.buckets.values()) {
145
- for (const waiter of bucket.queue) {
146
- waiter.reject(new Error('Rate limiter destroyed'));
147
- }
148
- bucket.queue = [];
149
- }
150
- }
151
- refill(bucket) {
152
- const now = Date.now();
153
- const elapsed = now - bucket.lastRefillAt;
154
- const tokensToAdd = elapsed * bucket.refillRate;
155
- bucket.tokens = Math.min(bucket.tokens + tokensToAdd, bucket.maxTokens);
156
- bucket.lastRefillAt = now;
157
- }
158
- drainQueue(bucket) {
159
- while (bucket.queue.length > 0 && bucket.tokens >= 1) {
160
- bucket.tokens -= 1;
161
- const waiter = bucket.queue.shift();
162
- waiter.resolve();
163
- }
164
- }
165
- ensureDrainTimer(service, bucket) {
166
- if (this.timers.has(service))
167
- return;
168
- const intervalMs = Math.max(10, Math.ceil(1 / bucket.refillRate));
169
- const timer = setInterval(() => {
170
- this.refill(bucket);
171
- this.drainQueue(bucket);
172
- if (bucket.queue.length === 0) {
173
- clearInterval(timer);
174
- this.timers.delete(service);
175
- }
176
- }, intervalMs);
177
- if (timer.unref)
178
- timer.unref();
179
- this.timers.set(service, timer);
180
- }
181
- }
182
- /** Global rate limiter registry */
183
- let _globalLimiter;
184
- export function getRateLimiterRegistry(overrides) {
185
- if (!_globalLimiter) {
186
- _globalLimiter = new RateLimiterRegistry(overrides);
187
- }
188
- return _globalLimiter;
189
- }
190
- export function resetRateLimiterRegistry() {
191
- _globalLimiter?.destroy();
192
- _globalLimiter = undefined;
193
- }
194
- //# sourceMappingURL=rate-limiter.js.map