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,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Filter Module
|
|
3
|
+
*
|
|
4
|
+
* Assesses quality of extracted Q&A pairs for inclusion in the knowledge base.
|
|
5
|
+
* Filters based on minimum length requirements, response time, and resolution indicators.
|
|
6
|
+
*/
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Default Configuration
|
|
9
|
+
// =============================================================================
|
|
10
|
+
const DEFAULT_CONFIG = {
|
|
11
|
+
minQuestionLength: 20, // At least a meaningful question
|
|
12
|
+
minResponseLength: 50, // At least a meaningful response
|
|
13
|
+
maxResponseTimeMs: 86400000 * 7, // 7 days max
|
|
14
|
+
minQualityScore: 0.4, // 40% minimum to pass
|
|
15
|
+
weights: {
|
|
16
|
+
questionLength: 0.15,
|
|
17
|
+
responseLength: 0.20,
|
|
18
|
+
responseTime: 0.20,
|
|
19
|
+
hasSubject: 0.10,
|
|
20
|
+
hasResolution: 0.20,
|
|
21
|
+
conversationDepth: 0.15,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Resolution Keywords
|
|
26
|
+
// =============================================================================
|
|
27
|
+
const POSITIVE_RESOLUTION_KEYWORDS = [
|
|
28
|
+
'resolved',
|
|
29
|
+
'completed',
|
|
30
|
+
'done',
|
|
31
|
+
'fixed',
|
|
32
|
+
'thank you',
|
|
33
|
+
'thanks',
|
|
34
|
+
'perfect',
|
|
35
|
+
'great',
|
|
36
|
+
'excellent',
|
|
37
|
+
'appreciate',
|
|
38
|
+
'helpful',
|
|
39
|
+
'solved',
|
|
40
|
+
'works',
|
|
41
|
+
'working',
|
|
42
|
+
'received',
|
|
43
|
+
'shipped',
|
|
44
|
+
'delivered',
|
|
45
|
+
'processed',
|
|
46
|
+
'confirmed',
|
|
47
|
+
];
|
|
48
|
+
const NEGATIVE_RESOLUTION_KEYWORDS = [
|
|
49
|
+
'still waiting',
|
|
50
|
+
'not resolved',
|
|
51
|
+
'unresolved',
|
|
52
|
+
'issue persists',
|
|
53
|
+
'problem continues',
|
|
54
|
+
'escalated',
|
|
55
|
+
'escalate',
|
|
56
|
+
'complaint',
|
|
57
|
+
'disappointed',
|
|
58
|
+
'frustrated',
|
|
59
|
+
'unacceptable',
|
|
60
|
+
];
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// Quality Filter Class
|
|
63
|
+
// =============================================================================
|
|
64
|
+
export class QualityFilter {
|
|
65
|
+
config;
|
|
66
|
+
constructor(config = {}) {
|
|
67
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Assess quality of a Q&A pair
|
|
71
|
+
*/
|
|
72
|
+
assess(input) {
|
|
73
|
+
const factors = [];
|
|
74
|
+
// 1. Question length factor
|
|
75
|
+
factors.push(this.assessQuestionLength(input.questionText));
|
|
76
|
+
// 2. Response length factor
|
|
77
|
+
factors.push(this.assessResponseLength(input.responseText));
|
|
78
|
+
// 3. Response time factor
|
|
79
|
+
if (input.responseTimeMs !== undefined) {
|
|
80
|
+
factors.push(this.assessResponseTime(input.responseTimeMs));
|
|
81
|
+
}
|
|
82
|
+
// 4. Has subject factor
|
|
83
|
+
factors.push(this.assessHasSubject(input.questionSubject));
|
|
84
|
+
// 5. Resolution indicator factor
|
|
85
|
+
factors.push(this.assessResolution(input.resolutionIndicator, input.questionText, input.responseText));
|
|
86
|
+
// 6. Conversation depth factor
|
|
87
|
+
factors.push(this.assessConversationDepth(input.conversationTurnCount));
|
|
88
|
+
// Calculate weighted score
|
|
89
|
+
let totalWeight = 0;
|
|
90
|
+
let weightedScore = 0;
|
|
91
|
+
for (const factor of factors) {
|
|
92
|
+
weightedScore += factor.score * factor.weight;
|
|
93
|
+
totalWeight += factor.weight;
|
|
94
|
+
}
|
|
95
|
+
const score = totalWeight > 0 ? weightedScore / totalWeight : 0;
|
|
96
|
+
const passed = score >= this.config.minQualityScore;
|
|
97
|
+
// Generate summary
|
|
98
|
+
const summary = this.generateSummary(factors, score, passed);
|
|
99
|
+
return {
|
|
100
|
+
score,
|
|
101
|
+
passed,
|
|
102
|
+
factors,
|
|
103
|
+
summary,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Quick check if Q&A pair meets minimum requirements
|
|
108
|
+
*/
|
|
109
|
+
meetsMinimumRequirements(input) {
|
|
110
|
+
return (input.questionText.length >= this.config.minQuestionLength &&
|
|
111
|
+
input.responseText.length >= this.config.minResponseLength);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Batch assess multiple Q&A pairs
|
|
115
|
+
*/
|
|
116
|
+
assessBatch(inputs) {
|
|
117
|
+
return inputs.map((input) => this.assess(input));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Filter batch to only passing entries
|
|
121
|
+
*/
|
|
122
|
+
filterPassing(inputs) {
|
|
123
|
+
return inputs
|
|
124
|
+
.map((input) => ({ input, assessment: this.assess(input) }))
|
|
125
|
+
.filter(({ assessment }) => assessment.passed);
|
|
126
|
+
}
|
|
127
|
+
// ===========================================================================
|
|
128
|
+
// Individual Factor Assessments
|
|
129
|
+
// ===========================================================================
|
|
130
|
+
assessQuestionLength(text) {
|
|
131
|
+
const length = text.trim().length;
|
|
132
|
+
const minLength = this.config.minQuestionLength;
|
|
133
|
+
const optimalLength = 200; // Questions around 200 chars are often well-formed
|
|
134
|
+
let score;
|
|
135
|
+
if (length < minLength) {
|
|
136
|
+
score = 0;
|
|
137
|
+
}
|
|
138
|
+
else if (length < optimalLength) {
|
|
139
|
+
score = (length - minLength) / (optimalLength - minLength) * 0.6 + 0.4;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Diminishing returns after optimal length
|
|
143
|
+
score = Math.min(1.0, 0.6 + 0.4 * Math.min(1, length / 500));
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
name: 'questionLength',
|
|
147
|
+
score,
|
|
148
|
+
weight: this.config.weights.questionLength,
|
|
149
|
+
details: `Question length: ${length} chars (min: ${minLength})`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
assessResponseLength(text) {
|
|
153
|
+
const length = text.trim().length;
|
|
154
|
+
const minLength = this.config.minResponseLength;
|
|
155
|
+
const optimalLength = 500; // Responses around 500 chars are often substantive
|
|
156
|
+
let score;
|
|
157
|
+
if (length < minLength) {
|
|
158
|
+
score = 0;
|
|
159
|
+
}
|
|
160
|
+
else if (length < optimalLength) {
|
|
161
|
+
score = (length - minLength) / (optimalLength - minLength) * 0.6 + 0.4;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Diminishing returns after optimal length
|
|
165
|
+
score = Math.min(1.0, 0.6 + 0.4 * Math.min(1, length / 1000));
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
name: 'responseLength',
|
|
169
|
+
score,
|
|
170
|
+
weight: this.config.weights.responseLength,
|
|
171
|
+
details: `Response length: ${length} chars (min: ${minLength})`,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
assessResponseTime(timeMs) {
|
|
175
|
+
const maxTime = this.config.maxResponseTimeMs;
|
|
176
|
+
const optimalTime = 3600000; // 1 hour - quick responses are valued
|
|
177
|
+
let score;
|
|
178
|
+
if (timeMs <= 0) {
|
|
179
|
+
score = 0.5; // Unknown - neutral score
|
|
180
|
+
}
|
|
181
|
+
else if (timeMs <= optimalTime) {
|
|
182
|
+
score = 1.0;
|
|
183
|
+
}
|
|
184
|
+
else if (timeMs <= maxTime) {
|
|
185
|
+
// Linear decrease from optimal to max
|
|
186
|
+
score = 1.0 - (timeMs - optimalTime) / (maxTime - optimalTime) * 0.6;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
score = 0.2; // Very slow but still usable
|
|
190
|
+
}
|
|
191
|
+
const hours = Math.round(timeMs / 3600000);
|
|
192
|
+
return {
|
|
193
|
+
name: 'responseTime',
|
|
194
|
+
score,
|
|
195
|
+
weight: this.config.weights.responseTime,
|
|
196
|
+
details: `Response time: ${hours}h`,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
assessHasSubject(subject) {
|
|
200
|
+
const hasSubject = !!subject && subject.trim().length > 5;
|
|
201
|
+
const score = hasSubject ? 1.0 : 0.3;
|
|
202
|
+
return {
|
|
203
|
+
name: 'hasSubject',
|
|
204
|
+
score,
|
|
205
|
+
weight: this.config.weights.hasSubject,
|
|
206
|
+
details: hasSubject ? 'Has meaningful subject' : 'No subject or too short',
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
assessResolution(indicator, questionText, responseText) {
|
|
210
|
+
// Check explicit indicator
|
|
211
|
+
if (indicator) {
|
|
212
|
+
const lowerIndicator = indicator.toLowerCase();
|
|
213
|
+
if (lowerIndicator.includes('resolved') || lowerIndicator.includes('completed')) {
|
|
214
|
+
return {
|
|
215
|
+
name: 'hasResolution',
|
|
216
|
+
score: 1.0,
|
|
217
|
+
weight: this.config.weights.hasResolution,
|
|
218
|
+
details: 'Explicit resolution indicator: ' + indicator,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Analyze text for resolution signals
|
|
223
|
+
const fullText = ((questionText || '') + ' ' + (responseText || '')).toLowerCase();
|
|
224
|
+
// Check for positive resolution keywords
|
|
225
|
+
const positiveCount = POSITIVE_RESOLUTION_KEYWORDS.filter((kw) => fullText.includes(kw)).length;
|
|
226
|
+
// Check for negative resolution keywords
|
|
227
|
+
const negativeCount = NEGATIVE_RESOLUTION_KEYWORDS.filter((kw) => fullText.includes(kw)).length;
|
|
228
|
+
let score;
|
|
229
|
+
let details;
|
|
230
|
+
if (negativeCount > 0) {
|
|
231
|
+
score = 0.3;
|
|
232
|
+
details = `Negative resolution signals detected (${negativeCount})`;
|
|
233
|
+
}
|
|
234
|
+
else if (positiveCount >= 3) {
|
|
235
|
+
score = 0.9;
|
|
236
|
+
details = `Strong positive resolution signals (${positiveCount})`;
|
|
237
|
+
}
|
|
238
|
+
else if (positiveCount >= 1) {
|
|
239
|
+
score = 0.7;
|
|
240
|
+
details = `Some positive resolution signals (${positiveCount})`;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
score = 0.5;
|
|
244
|
+
details = 'No clear resolution signals';
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
name: 'hasResolution',
|
|
248
|
+
score,
|
|
249
|
+
weight: this.config.weights.hasResolution,
|
|
250
|
+
details,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
assessConversationDepth(turnCount) {
|
|
254
|
+
if (!turnCount || turnCount <= 0) {
|
|
255
|
+
return {
|
|
256
|
+
name: 'conversationDepth',
|
|
257
|
+
score: 0.5,
|
|
258
|
+
weight: this.config.weights.conversationDepth,
|
|
259
|
+
details: 'Unknown conversation depth',
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// 2-4 turns is ideal (back and forth with resolution)
|
|
263
|
+
let score;
|
|
264
|
+
if (turnCount === 1) {
|
|
265
|
+
score = 0.6; // Single exchange - might be complete
|
|
266
|
+
}
|
|
267
|
+
else if (turnCount <= 4) {
|
|
268
|
+
score = 1.0; // Ideal depth
|
|
269
|
+
}
|
|
270
|
+
else if (turnCount <= 8) {
|
|
271
|
+
score = 0.7; // Getting long
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
score = 0.4; // Very long - might indicate difficulty
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
name: 'conversationDepth',
|
|
278
|
+
score,
|
|
279
|
+
weight: this.config.weights.conversationDepth,
|
|
280
|
+
details: `${turnCount} turns in conversation`,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
// ===========================================================================
|
|
284
|
+
// Summary Generation
|
|
285
|
+
// ===========================================================================
|
|
286
|
+
generateSummary(factors, score, passed) {
|
|
287
|
+
const scorePercent = Math.round(score * 100);
|
|
288
|
+
const issues = factors
|
|
289
|
+
.filter((f) => f.score < 0.5)
|
|
290
|
+
.map((f) => f.name)
|
|
291
|
+
.join(', ');
|
|
292
|
+
const strengths = factors
|
|
293
|
+
.filter((f) => f.score >= 0.8)
|
|
294
|
+
.map((f) => f.name)
|
|
295
|
+
.join(', ');
|
|
296
|
+
let summary = `Quality score: ${scorePercent}% (${passed ? 'PASSED' : 'FAILED'})`;
|
|
297
|
+
if (strengths) {
|
|
298
|
+
summary += ` | Strengths: ${strengths}`;
|
|
299
|
+
}
|
|
300
|
+
if (issues) {
|
|
301
|
+
summary += ` | Issues: ${issues}`;
|
|
302
|
+
}
|
|
303
|
+
return summary;
|
|
304
|
+
}
|
|
305
|
+
// ===========================================================================
|
|
306
|
+
// Configuration
|
|
307
|
+
// ===========================================================================
|
|
308
|
+
/**
|
|
309
|
+
* Update configuration
|
|
310
|
+
*/
|
|
311
|
+
updateConfig(config) {
|
|
312
|
+
this.config = { ...this.config, ...config };
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get current configuration
|
|
316
|
+
*/
|
|
317
|
+
getConfig() {
|
|
318
|
+
return { ...this.config };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// =============================================================================
|
|
322
|
+
// Singleton Instance
|
|
323
|
+
// =============================================================================
|
|
324
|
+
let qualityFilterInstance = null;
|
|
325
|
+
/**
|
|
326
|
+
* Get singleton quality filter instance
|
|
327
|
+
*/
|
|
328
|
+
export function getQualityFilter() {
|
|
329
|
+
if (!qualityFilterInstance) {
|
|
330
|
+
qualityFilterInstance = new QualityFilter();
|
|
331
|
+
}
|
|
332
|
+
return qualityFilterInstance;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Reset the singleton (for testing)
|
|
336
|
+
*/
|
|
337
|
+
export function resetQualityFilter() {
|
|
338
|
+
qualityFilterInstance = null;
|
|
339
|
+
}
|
|
340
|
+
// =============================================================================
|
|
341
|
+
// Utility Functions
|
|
342
|
+
// =============================================================================
|
|
343
|
+
/**
|
|
344
|
+
* Quick quality assessment using singleton
|
|
345
|
+
*/
|
|
346
|
+
export function assessQuality(input) {
|
|
347
|
+
return getQualityFilter().assess(input);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Quick check for minimum requirements
|
|
351
|
+
*/
|
|
352
|
+
export function meetsMinimumQuality(input) {
|
|
353
|
+
return getQualityFilter().meetsMinimumRequirements(input);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Infer resolution indicator from text
|
|
357
|
+
*/
|
|
358
|
+
export function inferResolutionIndicator(questionText, responseText) {
|
|
359
|
+
const fullText = (questionText + ' ' + responseText).toLowerCase();
|
|
360
|
+
const positiveCount = POSITIVE_RESOLUTION_KEYWORDS.filter((kw) => fullText.includes(kw)).length;
|
|
361
|
+
const negativeCount = NEGATIVE_RESOLUTION_KEYWORDS.filter((kw) => fullText.includes(kw)).length;
|
|
362
|
+
if (negativeCount > positiveCount) {
|
|
363
|
+
return 'ongoing';
|
|
364
|
+
}
|
|
365
|
+
else if (positiveCount >= 2) {
|
|
366
|
+
return 'resolved';
|
|
367
|
+
}
|
|
368
|
+
return 'unknown';
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=quality-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-filter.js","sourceRoot":"","sources":["../../src/extraction/quality-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
export interface RateLimiterConfig {
|
|
8
|
+
requestsPerMinute: number;
|
|
9
|
+
requestsPerSecond?: number;
|
|
10
|
+
maxConcurrent?: number;
|
|
11
|
+
enableRetry?: boolean;
|
|
12
|
+
maxRetries?: number;
|
|
13
|
+
baseDelayMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface RateLimitStatus {
|
|
16
|
+
available: boolean;
|
|
17
|
+
remainingRequests: number;
|
|
18
|
+
resetAtMs: number;
|
|
19
|
+
currentConcurrent: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class RateLimiter {
|
|
22
|
+
private config;
|
|
23
|
+
private tokens;
|
|
24
|
+
private lastRefill;
|
|
25
|
+
private currentConcurrent;
|
|
26
|
+
private requestTimes;
|
|
27
|
+
constructor(config: RateLimiterConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Acquire a token (blocks until available)
|
|
30
|
+
*/
|
|
31
|
+
acquire(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Try to acquire a token without blocking
|
|
34
|
+
*/
|
|
35
|
+
tryAcquire(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Release a concurrent slot
|
|
38
|
+
*/
|
|
39
|
+
release(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Execute a function with rate limiting
|
|
42
|
+
*/
|
|
43
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Execute with retry on rate limit errors
|
|
46
|
+
*/
|
|
47
|
+
executeWithRetry<T>(fn: () => Promise<T>, isRateLimitError?: (error: unknown) => boolean): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Get current rate limit status
|
|
50
|
+
*/
|
|
51
|
+
getStatus(): RateLimitStatus;
|
|
52
|
+
/**
|
|
53
|
+
* Consume a token
|
|
54
|
+
*/
|
|
55
|
+
private consumeToken;
|
|
56
|
+
/**
|
|
57
|
+
* Refill tokens based on elapsed time
|
|
58
|
+
*/
|
|
59
|
+
private refillTokens;
|
|
60
|
+
/**
|
|
61
|
+
* Default rate limit error detector
|
|
62
|
+
*/
|
|
63
|
+
private defaultIsRateLimitError;
|
|
64
|
+
/**
|
|
65
|
+
* Delay helper
|
|
66
|
+
*/
|
|
67
|
+
private delay;
|
|
68
|
+
/**
|
|
69
|
+
* Reset the rate limiter
|
|
70
|
+
*/
|
|
71
|
+
reset(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Get configuration
|
|
74
|
+
*/
|
|
75
|
+
getConfig(): Required<RateLimiterConfig>;
|
|
76
|
+
}
|
|
77
|
+
export declare const gmailRateLimiter: RateLimiter;
|
|
78
|
+
export declare const openaiRateLimiter: RateLimiter;
|
|
79
|
+
/**
|
|
80
|
+
* Create a rate-limited function
|
|
81
|
+
*/
|
|
82
|
+
export declare function rateLimited<T extends (...args: unknown[]) => Promise<unknown>>(fn: T, limiter: RateLimiter): T;
|
|
83
|
+
/**
|
|
84
|
+
* Batch execute with rate limiting
|
|
85
|
+
*/
|
|
86
|
+
export declare function batchExecute<T, R>(items: T[], fn: (item: T) => Promise<R>, limiter: RateLimiter, options?: {
|
|
87
|
+
concurrency?: number;
|
|
88
|
+
onProgress?: (completed: number, total: number) => void;
|
|
89
|
+
}): Promise<R[]>;
|
|
90
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/extraction/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,iBAAiB;IAEhC,iBAAiB,EAAE,MAAM,CAAC;IAG1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,WAAW,CAAC,EAAE,OAAO,CAAC;IAGtB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,YAAY,CAAgB;gBAExB,MAAM,EAAE,iBAAiB;IAcrC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;OAEG;IACH,UAAU,IAAI,OAAO;IAWrB;;OAEG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWlD;;OAEG;IACG,gBAAgB,CAAC,CAAC,EACtB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,gBAAgB,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAsC,GAC3E,OAAO,CAAC,CAAC,CAAC;IA4Bb;;OAEG;IACH,SAAS,IAAI,eAAe;IAyC5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,iBAAiB,CAAC;CAGzC;AAOD,eAAO,MAAM,gBAAgB,aAO3B,CAAC;AAGH,eAAO,MAAM,iBAAiB,aAO5B,CAAC;AAMH;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAC5E,EAAE,EAAE,CAAC,EACL,OAAO,EAAE,WAAW,GACnB,CAAC,CAIH;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EACrC,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAC9F,OAAO,CAAC,CAAC,EAAE,CAAC,CAwBd"}
|