catalist-support-agent 1.0.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 (140) hide show
  1. package/dist/admin-portal.d.ts +43 -0
  2. package/dist/admin-portal.d.ts.map +1 -0
  3. package/dist/admin-portal.js +166 -0
  4. package/dist/admin-portal.js.map +1 -0
  5. package/dist/analysis/entities.d.ts +73 -0
  6. package/dist/analysis/entities.d.ts.map +1 -0
  7. package/dist/analysis/entities.js +378 -0
  8. package/dist/analysis/entities.js.map +1 -0
  9. package/dist/analysis/index.d.ts +44 -0
  10. package/dist/analysis/index.d.ts.map +1 -0
  11. package/dist/analysis/index.js +243 -0
  12. package/dist/analysis/index.js.map +1 -0
  13. package/dist/analysis/intent.d.ts +49 -0
  14. package/dist/analysis/intent.d.ts.map +1 -0
  15. package/dist/analysis/intent.js +320 -0
  16. package/dist/analysis/intent.js.map +1 -0
  17. package/dist/analysis/sentiment.d.ts +57 -0
  18. package/dist/analysis/sentiment.d.ts.map +1 -0
  19. package/dist/analysis/sentiment.js +351 -0
  20. package/dist/analysis/sentiment.js.map +1 -0
  21. package/dist/brand/compliance.d.ts +122 -0
  22. package/dist/brand/compliance.d.ts.map +1 -0
  23. package/dist/brand/compliance.js +378 -0
  24. package/dist/brand/compliance.js.map +1 -0
  25. package/dist/brand/forbidden-terms.d.ts +99 -0
  26. package/dist/brand/forbidden-terms.d.ts.map +1 -0
  27. package/dist/brand/forbidden-terms.js +265 -0
  28. package/dist/brand/forbidden-terms.js.map +1 -0
  29. package/dist/brand/index.d.ts +10 -0
  30. package/dist/brand/index.d.ts.map +1 -0
  31. package/dist/brand/index.js +12 -0
  32. package/dist/brand/index.js.map +1 -0
  33. package/dist/config.d.ts +325 -0
  34. package/dist/config.d.ts.map +1 -0
  35. package/dist/config.js +492 -0
  36. package/dist/config.js.map +1 -0
  37. package/dist/delivery/index.d.ts +84 -0
  38. package/dist/delivery/index.d.ts.map +1 -0
  39. package/dist/delivery/index.js +435 -0
  40. package/dist/delivery/index.js.map +1 -0
  41. package/dist/embeddings/cache.d.ts +96 -0
  42. package/dist/embeddings/cache.d.ts.map +1 -0
  43. package/dist/embeddings/cache.js +193 -0
  44. package/dist/embeddings/cache.js.map +1 -0
  45. package/dist/embeddings/index.d.ts +152 -0
  46. package/dist/embeddings/index.d.ts.map +1 -0
  47. package/dist/embeddings/index.js +337 -0
  48. package/dist/embeddings/index.js.map +1 -0
  49. package/dist/embeddings/openai-client.d.ts +67 -0
  50. package/dist/embeddings/openai-client.d.ts.map +1 -0
  51. package/dist/embeddings/openai-client.js +190 -0
  52. package/dist/embeddings/openai-client.js.map +1 -0
  53. package/dist/errors.d.ts +302 -0
  54. package/dist/errors.d.ts.map +1 -0
  55. package/dist/errors.js +508 -0
  56. package/dist/errors.js.map +1 -0
  57. package/dist/escalation/index.d.ts +93 -0
  58. package/dist/escalation/index.d.ts.map +1 -0
  59. package/dist/escalation/index.js +436 -0
  60. package/dist/escalation/index.js.map +1 -0
  61. package/dist/extraction/deduplication.d.ts +97 -0
  62. package/dist/extraction/deduplication.d.ts.map +1 -0
  63. package/dist/extraction/deduplication.js +271 -0
  64. package/dist/extraction/deduplication.js.map +1 -0
  65. package/dist/extraction/gmail-extractor.d.ts +160 -0
  66. package/dist/extraction/gmail-extractor.d.ts.map +1 -0
  67. package/dist/extraction/gmail-extractor.js +396 -0
  68. package/dist/extraction/gmail-extractor.js.map +1 -0
  69. package/dist/extraction/gmail-token-manager.d.ts +36 -0
  70. package/dist/extraction/gmail-token-manager.d.ts.map +1 -0
  71. package/dist/extraction/gmail-token-manager.js +146 -0
  72. package/dist/extraction/gmail-token-manager.js.map +1 -0
  73. package/dist/extraction/index.d.ts +13 -0
  74. package/dist/extraction/index.d.ts.map +1 -0
  75. package/dist/extraction/index.js +20 -0
  76. package/dist/extraction/index.js.map +1 -0
  77. package/dist/extraction/pii-handler.d.ts +100 -0
  78. package/dist/extraction/pii-handler.d.ts.map +1 -0
  79. package/dist/extraction/pii-handler.js +295 -0
  80. package/dist/extraction/pii-handler.js.map +1 -0
  81. package/dist/extraction/pipeline.d.ts +94 -0
  82. package/dist/extraction/pipeline.d.ts.map +1 -0
  83. package/dist/extraction/pipeline.js +380 -0
  84. package/dist/extraction/pipeline.js.map +1 -0
  85. package/dist/extraction/quality-filter.d.ts +99 -0
  86. package/dist/extraction/quality-filter.d.ts.map +1 -0
  87. package/dist/extraction/quality-filter.js +370 -0
  88. package/dist/extraction/quality-filter.js.map +1 -0
  89. package/dist/extraction/rate-limiter.d.ts +90 -0
  90. package/dist/extraction/rate-limiter.d.ts.map +1 -0
  91. package/dist/extraction/rate-limiter.js +242 -0
  92. package/dist/extraction/rate-limiter.js.map +1 -0
  93. package/dist/extraction/state-manager.d.ts +126 -0
  94. package/dist/extraction/state-manager.d.ts.map +1 -0
  95. package/dist/extraction/state-manager.js +344 -0
  96. package/dist/extraction/state-manager.js.map +1 -0
  97. package/dist/generation/index.d.ts +75 -0
  98. package/dist/generation/index.d.ts.map +1 -0
  99. package/dist/generation/index.js +641 -0
  100. package/dist/generation/index.js.map +1 -0
  101. package/dist/index.d.ts +96 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +233 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/intake/index.d.ts +15 -0
  106. package/dist/intake/index.d.ts.map +1 -0
  107. package/dist/intake/index.js +19 -0
  108. package/dist/intake/index.js.map +1 -0
  109. package/dist/intake/normalizer.d.ts +163 -0
  110. package/dist/intake/normalizer.d.ts.map +1 -0
  111. package/dist/intake/normalizer.js +309 -0
  112. package/dist/intake/normalizer.js.map +1 -0
  113. package/dist/intake/postmark.d.ts +72 -0
  114. package/dist/intake/postmark.d.ts.map +1 -0
  115. package/dist/intake/postmark.js +276 -0
  116. package/dist/intake/postmark.js.map +1 -0
  117. package/dist/intake/slack.d.ts +106 -0
  118. package/dist/intake/slack.d.ts.map +1 -0
  119. package/dist/intake/slack.js +378 -0
  120. package/dist/intake/slack.js.map +1 -0
  121. package/dist/intake/twilio.d.ts +86 -0
  122. package/dist/intake/twilio.d.ts.map +1 -0
  123. package/dist/intake/twilio.js +283 -0
  124. package/dist/intake/twilio.js.map +1 -0
  125. package/dist/knowledge/index.d.ts +100 -0
  126. package/dist/knowledge/index.d.ts.map +1 -0
  127. package/dist/knowledge/index.js +516 -0
  128. package/dist/knowledge/index.js.map +1 -0
  129. package/dist/knowledge/invoice-resolver.d.ts +62 -0
  130. package/dist/knowledge/invoice-resolver.d.ts.map +1 -0
  131. package/dist/knowledge/invoice-resolver.js +267 -0
  132. package/dist/knowledge/invoice-resolver.js.map +1 -0
  133. package/dist/types.d.ts +535 -0
  134. package/dist/types.d.ts.map +1 -0
  135. package/dist/types.js +48 -0
  136. package/dist/types.js.map +1 -0
  137. package/ga-service-account.json +13 -0
  138. package/gmail-knowledge-migration.sql +149 -0
  139. package/nul +1 -0
  140. package/package.json +55 -0
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Rate Limiter Module
3
+ *
4
+ * Implements rate limiting for API calls (Gmail API, OpenAI API).
5
+ * Uses token bucket algorithm with sliding window for smooth rate limiting.
6
+ */
7
+ // =============================================================================
8
+ // Token Bucket Rate Limiter
9
+ // =============================================================================
10
+ export class RateLimiter {
11
+ config;
12
+ tokens;
13
+ lastRefill;
14
+ currentConcurrent = 0;
15
+ requestTimes = [];
16
+ constructor(config) {
17
+ this.config = {
18
+ requestsPerMinute: config.requestsPerMinute,
19
+ requestsPerSecond: config.requestsPerSecond ?? Math.ceil(config.requestsPerMinute / 60),
20
+ maxConcurrent: config.maxConcurrent ?? 10,
21
+ enableRetry: config.enableRetry ?? true,
22
+ maxRetries: config.maxRetries ?? 3,
23
+ baseDelayMs: config.baseDelayMs ?? 1000,
24
+ };
25
+ this.tokens = this.config.requestsPerMinute;
26
+ this.lastRefill = Date.now();
27
+ }
28
+ /**
29
+ * Acquire a token (blocks until available)
30
+ */
31
+ async acquire() {
32
+ while (true) {
33
+ const status = this.getStatus();
34
+ if (status.available) {
35
+ this.consumeToken();
36
+ return;
37
+ }
38
+ // Wait until we can proceed
39
+ const waitTime = Math.max(50, status.resetAtMs - Date.now());
40
+ await this.delay(Math.min(waitTime, 1000));
41
+ }
42
+ }
43
+ /**
44
+ * Try to acquire a token without blocking
45
+ */
46
+ tryAcquire() {
47
+ const status = this.getStatus();
48
+ if (status.available) {
49
+ this.consumeToken();
50
+ return true;
51
+ }
52
+ return false;
53
+ }
54
+ /**
55
+ * Release a concurrent slot
56
+ */
57
+ release() {
58
+ if (this.currentConcurrent > 0) {
59
+ this.currentConcurrent--;
60
+ }
61
+ }
62
+ /**
63
+ * Execute a function with rate limiting
64
+ */
65
+ async execute(fn) {
66
+ await this.acquire();
67
+ this.currentConcurrent++;
68
+ try {
69
+ return await fn();
70
+ }
71
+ finally {
72
+ this.release();
73
+ }
74
+ }
75
+ /**
76
+ * Execute with retry on rate limit errors
77
+ */
78
+ async executeWithRetry(fn, isRateLimitError = this.defaultIsRateLimitError) {
79
+ let lastError = null;
80
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
81
+ try {
82
+ return await this.execute(fn);
83
+ }
84
+ catch (error) {
85
+ lastError = error instanceof Error ? error : new Error(String(error));
86
+ if (!this.config.enableRetry || !isRateLimitError(error)) {
87
+ throw error;
88
+ }
89
+ if (attempt < this.config.maxRetries) {
90
+ // Exponential backoff with jitter
91
+ const delay = this.config.baseDelayMs * Math.pow(2, attempt) * (0.5 + Math.random() * 0.5);
92
+ console.warn(`Rate limit hit, retrying in ${Math.round(delay)}ms (attempt ${attempt + 1}/${this.config.maxRetries})`);
93
+ await this.delay(delay);
94
+ }
95
+ }
96
+ }
97
+ throw lastError || new Error('Rate limit exceeded after retries');
98
+ }
99
+ /**
100
+ * Get current rate limit status
101
+ */
102
+ getStatus() {
103
+ this.refillTokens();
104
+ const now = Date.now();
105
+ const oneMinuteAgo = now - 60000;
106
+ const oneSecondAgo = now - 1000;
107
+ // Clean up old request times
108
+ this.requestTimes = this.requestTimes.filter((t) => t > oneMinuteAgo);
109
+ // Count requests in last second
110
+ const requestsLastSecond = this.requestTimes.filter((t) => t > oneSecondAgo).length;
111
+ // Check all conditions
112
+ const hasTokens = this.tokens > 0;
113
+ const underSecondLimit = requestsLastSecond < this.config.requestsPerSecond;
114
+ const underConcurrentLimit = this.currentConcurrent < this.config.maxConcurrent;
115
+ const available = hasTokens && underSecondLimit && underConcurrentLimit;
116
+ // Calculate reset time
117
+ let resetAtMs = now;
118
+ if (!hasTokens) {
119
+ const nextRefillTime = this.lastRefill + 60000;
120
+ resetAtMs = Math.max(resetAtMs, nextRefillTime);
121
+ }
122
+ if (!underSecondLimit) {
123
+ const oldestSecondRequest = this.requestTimes.find((t) => t > oneSecondAgo);
124
+ if (oldestSecondRequest) {
125
+ resetAtMs = Math.max(resetAtMs, oldestSecondRequest + 1000);
126
+ }
127
+ }
128
+ return {
129
+ available,
130
+ remainingRequests: Math.floor(this.tokens),
131
+ resetAtMs,
132
+ currentConcurrent: this.currentConcurrent,
133
+ };
134
+ }
135
+ /**
136
+ * Consume a token
137
+ */
138
+ consumeToken() {
139
+ this.tokens--;
140
+ this.requestTimes.push(Date.now());
141
+ }
142
+ /**
143
+ * Refill tokens based on elapsed time
144
+ */
145
+ refillTokens() {
146
+ const now = Date.now();
147
+ const elapsed = now - this.lastRefill;
148
+ // Refill rate: tokens per millisecond
149
+ const refillRate = this.config.requestsPerMinute / 60000;
150
+ const tokensToAdd = elapsed * refillRate;
151
+ this.tokens = Math.min(this.config.requestsPerMinute, this.tokens + tokensToAdd);
152
+ this.lastRefill = now;
153
+ }
154
+ /**
155
+ * Default rate limit error detector
156
+ */
157
+ defaultIsRateLimitError(error) {
158
+ if (error instanceof Error) {
159
+ const message = error.message.toLowerCase();
160
+ return (message.includes('rate limit') ||
161
+ message.includes('too many requests') ||
162
+ message.includes('429'));
163
+ }
164
+ return false;
165
+ }
166
+ /**
167
+ * Delay helper
168
+ */
169
+ delay(ms) {
170
+ return new Promise((resolve) => setTimeout(resolve, ms));
171
+ }
172
+ /**
173
+ * Reset the rate limiter
174
+ */
175
+ reset() {
176
+ this.tokens = this.config.requestsPerMinute;
177
+ this.lastRefill = Date.now();
178
+ this.currentConcurrent = 0;
179
+ this.requestTimes = [];
180
+ }
181
+ /**
182
+ * Get configuration
183
+ */
184
+ getConfig() {
185
+ return { ...this.config };
186
+ }
187
+ }
188
+ // =============================================================================
189
+ // Pre-configured Rate Limiters
190
+ // =============================================================================
191
+ // Gmail API: 250 queries per second (but we'll be more conservative)
192
+ export const gmailRateLimiter = new RateLimiter({
193
+ requestsPerMinute: 60, // Conservative limit
194
+ requestsPerSecond: 5,
195
+ maxConcurrent: 5,
196
+ enableRetry: true,
197
+ maxRetries: 3,
198
+ baseDelayMs: 2000,
199
+ });
200
+ // OpenAI API: 3000 RPM for embeddings
201
+ export const openaiRateLimiter = new RateLimiter({
202
+ requestsPerMinute: 3000,
203
+ requestsPerSecond: 50,
204
+ maxConcurrent: 20,
205
+ enableRetry: true,
206
+ maxRetries: 3,
207
+ baseDelayMs: 1000,
208
+ });
209
+ // =============================================================================
210
+ // Utility Functions
211
+ // =============================================================================
212
+ /**
213
+ * Create a rate-limited function
214
+ */
215
+ export function rateLimited(fn, limiter) {
216
+ return (async (...args) => {
217
+ return limiter.execute(() => fn(...args));
218
+ });
219
+ }
220
+ /**
221
+ * Batch execute with rate limiting
222
+ */
223
+ export async function batchExecute(items, fn, limiter, options = {}) {
224
+ const { concurrency = 5, onProgress } = options;
225
+ const results = [];
226
+ let completed = 0;
227
+ // Process in chunks
228
+ for (let i = 0; i < items.length; i += concurrency) {
229
+ const chunk = items.slice(i, i + concurrency);
230
+ const chunkResults = await Promise.all(chunk.map(async (item) => {
231
+ const result = await limiter.execute(() => fn(item));
232
+ completed++;
233
+ if (onProgress) {
234
+ onProgress(completed, items.length);
235
+ }
236
+ return result;
237
+ }));
238
+ results.push(...chunkResults);
239
+ }
240
+ return results;
241
+ }
242
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/extraction/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * State Manager Module
3
+ *
4
+ * Tracks extraction state for incremental Gmail sync.
5
+ * Uses Gmail History API to only process new emails since last extraction.
6
+ */
7
+ export interface ExtractionState {
8
+ id: number;
9
+ emailAddress: string;
10
+ lastHistoryId: string | null;
11
+ lastExtractedAt: Date | null;
12
+ totalEntriesExtracted: number;
13
+ lastBatchId: string | null;
14
+ consecutiveErrors: number;
15
+ lastError: string | null;
16
+ lastErrorAt: Date | null;
17
+ createdAt: Date;
18
+ updatedAt: Date;
19
+ }
20
+ export interface BatchInfo {
21
+ id: string;
22
+ emailAccount: string;
23
+ dateRangeStart: Date;
24
+ dateRangeEnd: Date;
25
+ status: 'pending' | 'in_progress' | 'completed' | 'failed' | 'partial';
26
+ totalThreadsFound: number;
27
+ threadsProcessed: number;
28
+ entriesCreated: number;
29
+ entriesSkipped: number;
30
+ errorsEncountered: number;
31
+ startedAt: Date | null;
32
+ completedAt: Date | null;
33
+ errorLog: Array<{
34
+ timestamp: string;
35
+ error: string;
36
+ }>;
37
+ configUsed: Record<string, unknown>;
38
+ createdAt: Date;
39
+ updatedAt: Date;
40
+ }
41
+ export interface StateManagerConfig {
42
+ supabaseUrl: string;
43
+ supabaseServiceRoleKey: string;
44
+ }
45
+ export declare class StateManager {
46
+ private supabase;
47
+ constructor(config: StateManagerConfig);
48
+ /**
49
+ * Get extraction state for an email account
50
+ */
51
+ getState(emailAddress: string): Promise<ExtractionState | null>;
52
+ /**
53
+ * Create or get extraction state
54
+ */
55
+ getOrCreateState(emailAddress: string): Promise<ExtractionState>;
56
+ /**
57
+ * Update extraction state after successful extraction
58
+ */
59
+ updateStateSuccess(emailAddress: string, updates: {
60
+ historyId?: string;
61
+ entriesExtracted?: number;
62
+ batchId?: string;
63
+ }): Promise<void>;
64
+ /**
65
+ * Record extraction error
66
+ */
67
+ recordError(emailAddress: string, errorMessage: string): Promise<void>;
68
+ /**
69
+ * Check if we should back off due to errors
70
+ */
71
+ shouldBackOff(emailAddress: string, maxConsecutiveErrors?: number): Promise<boolean>;
72
+ /**
73
+ * Create a new import batch
74
+ */
75
+ createBatch(emailAccount: string, dateRangeStart: Date, dateRangeEnd: Date, config?: Record<string, unknown>): Promise<string>;
76
+ /**
77
+ * Start a batch (mark as in_progress)
78
+ */
79
+ startBatch(batchId: string, totalThreads: number): Promise<void>;
80
+ /**
81
+ * Update batch progress
82
+ */
83
+ updateBatchProgress(batchId: string, progress: {
84
+ threadsProcessed?: number;
85
+ entriesCreated?: number;
86
+ entriesSkipped?: number;
87
+ errorsEncountered?: number;
88
+ }): Promise<void>;
89
+ /**
90
+ * Add error to batch error log
91
+ */
92
+ addBatchError(batchId: string, errorMessage: string): Promise<void>;
93
+ /**
94
+ * Complete a batch
95
+ */
96
+ completeBatch(batchId: string, status?: 'completed' | 'failed' | 'partial'): Promise<void>;
97
+ /**
98
+ * Get batch info
99
+ */
100
+ getBatch(batchId: string): Promise<BatchInfo | null>;
101
+ /**
102
+ * Get recent batches for an email account
103
+ */
104
+ getRecentBatches(emailAccount: string, limit?: number): Promise<BatchInfo[]>;
105
+ /**
106
+ * Get overall extraction statistics
107
+ */
108
+ getStats(): Promise<{
109
+ totalEntries: number;
110
+ pendingEntries: number;
111
+ approvedEntries: number;
112
+ entriesWithEmbeddings: number;
113
+ recentBatches: BatchInfo[];
114
+ }>;
115
+ private mapStateRow;
116
+ private mapBatchRow;
117
+ }
118
+ /**
119
+ * Get singleton state manager instance
120
+ */
121
+ export declare function getStateManager(): StateManager;
122
+ /**
123
+ * Reset the singleton (for testing)
124
+ */
125
+ export declare function resetStateManager(): void;
126
+ //# sourceMappingURL=state-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../src/extraction/state-manager.ts"],"names":[],"mappings":"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"}