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.
- package/dist/admin-portal.d.ts +43 -0
- package/dist/admin-portal.d.ts.map +1 -0
- package/dist/admin-portal.js +166 -0
- package/dist/admin-portal.js.map +1 -0
- package/dist/analysis/entities.d.ts +73 -0
- package/dist/analysis/entities.d.ts.map +1 -0
- package/dist/analysis/entities.js +378 -0
- package/dist/analysis/entities.js.map +1 -0
- package/dist/analysis/index.d.ts +44 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +243 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/intent.d.ts +49 -0
- package/dist/analysis/intent.d.ts.map +1 -0
- package/dist/analysis/intent.js +320 -0
- package/dist/analysis/intent.js.map +1 -0
- package/dist/analysis/sentiment.d.ts +57 -0
- package/dist/analysis/sentiment.d.ts.map +1 -0
- package/dist/analysis/sentiment.js +351 -0
- package/dist/analysis/sentiment.js.map +1 -0
- package/dist/brand/compliance.d.ts +122 -0
- package/dist/brand/compliance.d.ts.map +1 -0
- package/dist/brand/compliance.js +378 -0
- package/dist/brand/compliance.js.map +1 -0
- package/dist/brand/forbidden-terms.d.ts +99 -0
- package/dist/brand/forbidden-terms.d.ts.map +1 -0
- package/dist/brand/forbidden-terms.js +265 -0
- package/dist/brand/forbidden-terms.js.map +1 -0
- package/dist/brand/index.d.ts +10 -0
- package/dist/brand/index.d.ts.map +1 -0
- package/dist/brand/index.js +12 -0
- package/dist/brand/index.js.map +1 -0
- package/dist/config.d.ts +325 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +492 -0
- package/dist/config.js.map +1 -0
- package/dist/delivery/index.d.ts +84 -0
- package/dist/delivery/index.d.ts.map +1 -0
- package/dist/delivery/index.js +435 -0
- package/dist/delivery/index.js.map +1 -0
- package/dist/embeddings/cache.d.ts +96 -0
- package/dist/embeddings/cache.d.ts.map +1 -0
- package/dist/embeddings/cache.js +193 -0
- package/dist/embeddings/cache.js.map +1 -0
- package/dist/embeddings/index.d.ts +152 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +337 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/openai-client.d.ts +67 -0
- package/dist/embeddings/openai-client.d.ts.map +1 -0
- package/dist/embeddings/openai-client.js +190 -0
- package/dist/embeddings/openai-client.js.map +1 -0
- package/dist/errors.d.ts +302 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +508 -0
- package/dist/errors.js.map +1 -0
- package/dist/escalation/index.d.ts +93 -0
- package/dist/escalation/index.d.ts.map +1 -0
- package/dist/escalation/index.js +436 -0
- package/dist/escalation/index.js.map +1 -0
- package/dist/extraction/deduplication.d.ts +97 -0
- package/dist/extraction/deduplication.d.ts.map +1 -0
- package/dist/extraction/deduplication.js +271 -0
- package/dist/extraction/deduplication.js.map +1 -0
- package/dist/extraction/gmail-extractor.d.ts +160 -0
- package/dist/extraction/gmail-extractor.d.ts.map +1 -0
- package/dist/extraction/gmail-extractor.js +396 -0
- package/dist/extraction/gmail-extractor.js.map +1 -0
- package/dist/extraction/gmail-token-manager.d.ts +36 -0
- package/dist/extraction/gmail-token-manager.d.ts.map +1 -0
- package/dist/extraction/gmail-token-manager.js +146 -0
- package/dist/extraction/gmail-token-manager.js.map +1 -0
- package/dist/extraction/index.d.ts +13 -0
- package/dist/extraction/index.d.ts.map +1 -0
- package/dist/extraction/index.js +20 -0
- package/dist/extraction/index.js.map +1 -0
- package/dist/extraction/pii-handler.d.ts +100 -0
- package/dist/extraction/pii-handler.d.ts.map +1 -0
- package/dist/extraction/pii-handler.js +295 -0
- package/dist/extraction/pii-handler.js.map +1 -0
- package/dist/extraction/pipeline.d.ts +94 -0
- package/dist/extraction/pipeline.d.ts.map +1 -0
- package/dist/extraction/pipeline.js +380 -0
- package/dist/extraction/pipeline.js.map +1 -0
- package/dist/extraction/quality-filter.d.ts +99 -0
- package/dist/extraction/quality-filter.d.ts.map +1 -0
- package/dist/extraction/quality-filter.js +370 -0
- package/dist/extraction/quality-filter.js.map +1 -0
- package/dist/extraction/rate-limiter.d.ts +90 -0
- package/dist/extraction/rate-limiter.d.ts.map +1 -0
- package/dist/extraction/rate-limiter.js +242 -0
- package/dist/extraction/rate-limiter.js.map +1 -0
- package/dist/extraction/state-manager.d.ts +126 -0
- package/dist/extraction/state-manager.d.ts.map +1 -0
- package/dist/extraction/state-manager.js +344 -0
- package/dist/extraction/state-manager.js.map +1 -0
- package/dist/generation/index.d.ts +75 -0
- package/dist/generation/index.d.ts.map +1 -0
- package/dist/generation/index.js +641 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +233 -0
- package/dist/index.js.map +1 -0
- package/dist/intake/index.d.ts +15 -0
- package/dist/intake/index.d.ts.map +1 -0
- package/dist/intake/index.js +19 -0
- package/dist/intake/index.js.map +1 -0
- package/dist/intake/normalizer.d.ts +163 -0
- package/dist/intake/normalizer.d.ts.map +1 -0
- package/dist/intake/normalizer.js +309 -0
- package/dist/intake/normalizer.js.map +1 -0
- package/dist/intake/postmark.d.ts +72 -0
- package/dist/intake/postmark.d.ts.map +1 -0
- package/dist/intake/postmark.js +276 -0
- package/dist/intake/postmark.js.map +1 -0
- package/dist/intake/slack.d.ts +106 -0
- package/dist/intake/slack.d.ts.map +1 -0
- package/dist/intake/slack.js +378 -0
- package/dist/intake/slack.js.map +1 -0
- package/dist/intake/twilio.d.ts +86 -0
- package/dist/intake/twilio.d.ts.map +1 -0
- package/dist/intake/twilio.js +283 -0
- package/dist/intake/twilio.js.map +1 -0
- package/dist/knowledge/index.d.ts +100 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +516 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/invoice-resolver.d.ts +62 -0
- package/dist/knowledge/invoice-resolver.d.ts.map +1 -0
- package/dist/knowledge/invoice-resolver.js +267 -0
- package/dist/knowledge/invoice-resolver.js.map +1 -0
- package/dist/types.d.ts +535 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +48 -0
- package/dist/types.js.map +1 -0
- package/ga-service-account.json +13 -0
- package/gmail-knowledge-migration.sql +149 -0
- package/nul +1 -0
- 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":"AAAA;;;;;GAKG;AAQH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,IAAI,CAAC;IACrB,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAMD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAiB;gBAErB,MAAM,EAAE,kBAAkB;IAQtC;;OAEG;IACG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAcrE;;OAEG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA0BtE;;OAEG;IACG,kBAAkB,CACtB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC,IAAI,CAAC;IAsChB;;OAEG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5E;;OAEG;IACG,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,oBAAoB,GAAE,MAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAa7F;;OAEG;IACG,WAAW,CACf,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,IAAI,EACpB,YAAY,EAAE,IAAI,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC;IAoBlB;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAetE;;OAEG;IACG,mBAAmB,CACvB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;QACR,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,GACA,OAAO,CAAC,IAAI,CAAC;IA0BhB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BzE;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,WAAW,GAAG,QAAQ,GAAG,SAAuB,GACvD,OAAO,CAAC,IAAI,CAAC;IAchB;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAc1D;;OAEG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAmBtF;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,aAAa,EAAE,SAAS,EAAE,CAAC;KAC5B,CAAC;IA0BF,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,WAAW;CAoBpB;AAQD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAgB9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|