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,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand Compliance Utilities
|
|
3
|
+
*
|
|
4
|
+
* Validates response text against Catalist brand guidelines:
|
|
5
|
+
* - Ensures marketplace-appropriate language
|
|
6
|
+
* - Rejects vendor/distributor-style communication
|
|
7
|
+
* - Enforces tone guidelines based on customer sentiment
|
|
8
|
+
* - Validates response passes brand test before sending
|
|
9
|
+
*
|
|
10
|
+
* CRITICAL: Every generated response MUST pass brand compliance before delivery.
|
|
11
|
+
*/
|
|
12
|
+
import { config } from '../config.js';
|
|
13
|
+
import { ForbiddenTermsDetector, scanForForbiddenTermsDetailed, } from './forbidden-terms.js';
|
|
14
|
+
import { ForbiddenTermsDetectedError, BrandComplianceError } from '../errors.js';
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Brand Voice Guidelines
|
|
17
|
+
// =============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Brand voice characteristics by sentiment context
|
|
20
|
+
*/
|
|
21
|
+
const BRAND_VOICE_GUIDELINES = {
|
|
22
|
+
// When customer is positive/satisfied
|
|
23
|
+
positive: {
|
|
24
|
+
tone: 'warm, appreciative, professional',
|
|
25
|
+
avoid: ['overly casual', 'excessive exclamation marks', 'slang'],
|
|
26
|
+
emphasis: ['gratitude', 'partnership', 'continued support'],
|
|
27
|
+
},
|
|
28
|
+
// When customer is neutral
|
|
29
|
+
neutral: {
|
|
30
|
+
tone: 'professional, helpful, clear',
|
|
31
|
+
avoid: ['overly formal', 'jargon', 'condescending'],
|
|
32
|
+
emphasis: ['clarity', 'efficiency', 'value'],
|
|
33
|
+
},
|
|
34
|
+
// When customer is negative/frustrated
|
|
35
|
+
negative: {
|
|
36
|
+
tone: 'empathetic, solution-focused, patient',
|
|
37
|
+
avoid: ['defensive', 'dismissive', 'blame-shifting'],
|
|
38
|
+
emphasis: ['acknowledgment', 'accountability', 'resolution'],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Terms we prefer over alternatives (brand positioning)
|
|
43
|
+
*/
|
|
44
|
+
const PREFERRED_TERMINOLOGY = {
|
|
45
|
+
// We are a marketplace, not a distributor
|
|
46
|
+
'wholesale distributor': 'B2B marketplace',
|
|
47
|
+
'wholesale supplier': 'marketplace',
|
|
48
|
+
distributor: 'marketplace',
|
|
49
|
+
vendor: 'brand partner',
|
|
50
|
+
supplier: 'seller',
|
|
51
|
+
customer: 'buyer',
|
|
52
|
+
'wholesale price': 'marketplace price',
|
|
53
|
+
'wholesale pricing': 'marketplace pricing',
|
|
54
|
+
'wholesale account': 'buyer account',
|
|
55
|
+
// Preferred brand terminology
|
|
56
|
+
catalist: 'Catalist',
|
|
57
|
+
'catalist deals': 'Catalist',
|
|
58
|
+
'catalist group': 'Catalist',
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Phrases that indicate vendor/distributor positioning (should be avoided)
|
|
62
|
+
*/
|
|
63
|
+
const VENDOR_STYLE_PHRASES = [
|
|
64
|
+
'we carry',
|
|
65
|
+
'we stock',
|
|
66
|
+
'our inventory',
|
|
67
|
+
'our warehouse',
|
|
68
|
+
'we distribute',
|
|
69
|
+
'our distribution',
|
|
70
|
+
'we wholesale',
|
|
71
|
+
'wholesale to you',
|
|
72
|
+
'we are a distributor',
|
|
73
|
+
'we are distributors',
|
|
74
|
+
'as your distributor',
|
|
75
|
+
'as your supplier',
|
|
76
|
+
'as a wholesale',
|
|
77
|
+
];
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Brand Terminology Enforcer
|
|
80
|
+
// =============================================================================
|
|
81
|
+
export class BrandTerminologyEnforcer {
|
|
82
|
+
preferredTerms;
|
|
83
|
+
vendorPhrasePatterns;
|
|
84
|
+
constructor() {
|
|
85
|
+
// Build preferred term replacement patterns
|
|
86
|
+
this.preferredTerms = new Map();
|
|
87
|
+
const customTerms = config.brandCompliance.enforcedTerminology?.preferredTerms ?? {};
|
|
88
|
+
const allPreferredTerms = { ...PREFERRED_TERMINOLOGY, ...customTerms };
|
|
89
|
+
for (const [incorrect, correct] of Object.entries(allPreferredTerms)) {
|
|
90
|
+
const pattern = new RegExp(`\\b${this.escapeRegex(incorrect)}\\b`, 'gi');
|
|
91
|
+
this.preferredTerms.set(pattern, correct);
|
|
92
|
+
}
|
|
93
|
+
// Build vendor phrase detection patterns
|
|
94
|
+
this.vendorPhrasePatterns = VENDOR_STYLE_PHRASES.map((phrase) => new RegExp(`\\b${this.escapeRegex(phrase)}\\b`, 'gi'));
|
|
95
|
+
}
|
|
96
|
+
escapeRegex(text) {
|
|
97
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if text contains vendor-style positioning
|
|
101
|
+
*/
|
|
102
|
+
containsVendorStyleLanguage(text) {
|
|
103
|
+
const foundPhrases = [];
|
|
104
|
+
for (const pattern of this.vendorPhrasePatterns) {
|
|
105
|
+
pattern.lastIndex = 0;
|
|
106
|
+
const match = text.match(pattern);
|
|
107
|
+
if (match) {
|
|
108
|
+
foundPhrases.push(...match);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
found: foundPhrases.length > 0,
|
|
113
|
+
phrases: [...new Set(foundPhrases)],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Suggest corrections for non-preferred terminology
|
|
118
|
+
*/
|
|
119
|
+
suggestCorrections(text) {
|
|
120
|
+
const corrections = [];
|
|
121
|
+
for (const [pattern, replacement] of this.preferredTerms) {
|
|
122
|
+
pattern.lastIndex = 0;
|
|
123
|
+
const matches = text.match(pattern);
|
|
124
|
+
if (matches) {
|
|
125
|
+
for (const match of matches) {
|
|
126
|
+
corrections.push({
|
|
127
|
+
original: match,
|
|
128
|
+
suggested: replacement,
|
|
129
|
+
reason: `Use "${replacement}" instead of "${match}" for brand-consistent messaging`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return corrections;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Apply terminology corrections to text
|
|
138
|
+
*/
|
|
139
|
+
applyCorrections(text) {
|
|
140
|
+
let corrected = text;
|
|
141
|
+
for (const [pattern, replacement] of this.preferredTerms) {
|
|
142
|
+
corrected = corrected.replace(pattern, replacement);
|
|
143
|
+
}
|
|
144
|
+
return corrected;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// =============================================================================
|
|
148
|
+
// Brand Compliance Checker
|
|
149
|
+
// =============================================================================
|
|
150
|
+
export class BrandComplianceChecker {
|
|
151
|
+
forbiddenTermsDetector;
|
|
152
|
+
terminologyEnforcer;
|
|
153
|
+
constructor() {
|
|
154
|
+
this.forbiddenTermsDetector = new ForbiddenTermsDetector();
|
|
155
|
+
this.terminologyEnforcer = new BrandTerminologyEnforcer();
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Perform comprehensive brand compliance check on text
|
|
159
|
+
*/
|
|
160
|
+
check(text, sentiment = 'neutral') {
|
|
161
|
+
const now = new Date().toISOString();
|
|
162
|
+
// 1. Check for forbidden terms (CRITICAL)
|
|
163
|
+
const forbiddenTermsResult = scanForForbiddenTermsDetailed(text);
|
|
164
|
+
// 2. Check for vendor-style language
|
|
165
|
+
const vendorStyleCheck = this.terminologyEnforcer.containsVendorStyleLanguage(text);
|
|
166
|
+
// 3. Get terminology corrections
|
|
167
|
+
const terminologyCorrections = this.terminologyEnforcer.suggestCorrections(text);
|
|
168
|
+
// 4. Check tone issues based on sentiment context
|
|
169
|
+
const toneIssues = this.checkToneIssues(text, sentiment);
|
|
170
|
+
// 5. Calculate overall score
|
|
171
|
+
let score = 100;
|
|
172
|
+
// Forbidden terms = immediate fail
|
|
173
|
+
if (forbiddenTermsResult.hasForbiddenTerms) {
|
|
174
|
+
score = 0;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// Vendor-style language: -30 points per phrase (max -60)
|
|
178
|
+
score -= Math.min(vendorStyleCheck.phrases.length * 30, 60);
|
|
179
|
+
// Terminology issues: -5 points per issue (max -20)
|
|
180
|
+
score -= Math.min(terminologyCorrections.length * 5, 20);
|
|
181
|
+
// Tone issues: -10 points per issue (max -20)
|
|
182
|
+
score -= Math.min(toneIssues.length * 10, 20);
|
|
183
|
+
score = Math.max(0, score);
|
|
184
|
+
}
|
|
185
|
+
// 6. Determine overall status
|
|
186
|
+
let overallStatus;
|
|
187
|
+
if (forbiddenTermsResult.hasForbiddenTerms) {
|
|
188
|
+
overallStatus = {
|
|
189
|
+
status: 'blocked',
|
|
190
|
+
detectedTerms: forbiddenTermsResult.detectedTerms,
|
|
191
|
+
blockedAt: now,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
else if (score < 70 || vendorStyleCheck.found) {
|
|
195
|
+
overallStatus = {
|
|
196
|
+
status: 'flagged',
|
|
197
|
+
score,
|
|
198
|
+
issues: [
|
|
199
|
+
...vendorStyleCheck.phrases.map((p) => `Vendor-style phrase: "${p}"`),
|
|
200
|
+
...terminologyCorrections.map((c) => c.reason),
|
|
201
|
+
...toneIssues,
|
|
202
|
+
],
|
|
203
|
+
checkedAt: now,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
overallStatus = {
|
|
208
|
+
status: 'compliant',
|
|
209
|
+
score,
|
|
210
|
+
checkedAt: now,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
passed: overallStatus.status === 'compliant',
|
|
215
|
+
score,
|
|
216
|
+
forbiddenTermsResult,
|
|
217
|
+
vendorStyleCheck,
|
|
218
|
+
terminologyCorrections,
|
|
219
|
+
toneIssues,
|
|
220
|
+
overallStatus,
|
|
221
|
+
checkedAt: now,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check for tone issues based on sentiment context
|
|
226
|
+
*/
|
|
227
|
+
checkToneIssues(text, sentiment) {
|
|
228
|
+
const issues = [];
|
|
229
|
+
const guidelines = BRAND_VOICE_GUIDELINES[sentiment];
|
|
230
|
+
const lowerText = text.toLowerCase();
|
|
231
|
+
// Check for things to avoid based on sentiment
|
|
232
|
+
if (sentiment === 'negative') {
|
|
233
|
+
// Check for defensive language
|
|
234
|
+
if (lowerText.includes('but you') ||
|
|
235
|
+
lowerText.includes('however, you') ||
|
|
236
|
+
lowerText.includes("it's not our")) {
|
|
237
|
+
issues.push('Avoid defensive language when responding to negative sentiment');
|
|
238
|
+
}
|
|
239
|
+
// Check for dismissive language
|
|
240
|
+
if (lowerText.includes("that's just") ||
|
|
241
|
+
lowerText.includes('simply') ||
|
|
242
|
+
lowerText.includes('just need to')) {
|
|
243
|
+
issues.push('Avoid dismissive language that minimizes customer concerns');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (sentiment === 'positive') {
|
|
247
|
+
// Check for excessive exclamation marks
|
|
248
|
+
const exclamationCount = (text.match(/!/g) ?? []).length;
|
|
249
|
+
if (exclamationCount > 2) {
|
|
250
|
+
issues.push('Reduce exclamation marks for professional tone');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Universal checks
|
|
254
|
+
// All caps words (excluding common acronyms)
|
|
255
|
+
const capsWords = text.match(/\b[A-Z]{4,}\b/g) ?? [];
|
|
256
|
+
const nonAcronymCaps = capsWords.filter((w) => !['ASAP', 'FYI', 'ETA', 'SKU', 'MOQ', 'MSRP', 'COD', 'FOB'].includes(w));
|
|
257
|
+
if (nonAcronymCaps.length > 0) {
|
|
258
|
+
issues.push('Avoid all-caps text for professional tone');
|
|
259
|
+
}
|
|
260
|
+
return issues;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Validate a generated response before sending
|
|
264
|
+
*/
|
|
265
|
+
validateResponse(responseText, sentiment = 'neutral') {
|
|
266
|
+
const complianceCheck = this.check(responseText, sentiment);
|
|
267
|
+
const errors = [];
|
|
268
|
+
const warnings = [];
|
|
269
|
+
// Forbidden terms = error (cannot send)
|
|
270
|
+
if (complianceCheck.forbiddenTermsResult.hasForbiddenTerms) {
|
|
271
|
+
errors.push(`Response contains forbidden terms: ${complianceCheck.forbiddenTermsResult.detectedTerms.join(', ')}`);
|
|
272
|
+
}
|
|
273
|
+
// Vendor-style language = error in strict mode, warning otherwise
|
|
274
|
+
if (complianceCheck.vendorStyleCheck.found) {
|
|
275
|
+
const message = `Response contains vendor-style language: ${complianceCheck.vendorStyleCheck.phrases.join(', ')}`;
|
|
276
|
+
if (config.brandCompliance.voiceEnforcementLevel === 'strict') {
|
|
277
|
+
errors.push(message);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
warnings.push(message);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Terminology corrections = warnings
|
|
284
|
+
for (const correction of complianceCheck.terminologyCorrections) {
|
|
285
|
+
warnings.push(correction.reason);
|
|
286
|
+
}
|
|
287
|
+
// Tone issues = warnings
|
|
288
|
+
for (const issue of complianceCheck.toneIssues) {
|
|
289
|
+
warnings.push(issue);
|
|
290
|
+
}
|
|
291
|
+
const canBeSent = errors.length === 0 ||
|
|
292
|
+
(!config.brandCompliance.preSendValidation &&
|
|
293
|
+
!complianceCheck.forbiddenTermsResult.hasForbiddenTerms);
|
|
294
|
+
const requiresHumanReview = complianceCheck.forbiddenTermsResult.hasForbiddenTerms ||
|
|
295
|
+
(config.brandCompliance.voiceEnforcementLevel === 'strict' &&
|
|
296
|
+
complianceCheck.vendorStyleCheck.found);
|
|
297
|
+
return {
|
|
298
|
+
isValid: complianceCheck.passed,
|
|
299
|
+
complianceCheck,
|
|
300
|
+
errors,
|
|
301
|
+
warnings,
|
|
302
|
+
canBeSent,
|
|
303
|
+
requiresHumanReview,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get suggested improvements for a response
|
|
308
|
+
*/
|
|
309
|
+
getSuggestedImprovements(responseText) {
|
|
310
|
+
let improved = responseText;
|
|
311
|
+
// Apply terminology corrections
|
|
312
|
+
improved = this.terminologyEnforcer.applyCorrections(improved);
|
|
313
|
+
return improved;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// =============================================================================
|
|
317
|
+
// Singleton and Utility Functions
|
|
318
|
+
// =============================================================================
|
|
319
|
+
let defaultChecker = null;
|
|
320
|
+
export function getDefaultChecker() {
|
|
321
|
+
if (!defaultChecker) {
|
|
322
|
+
defaultChecker = new BrandComplianceChecker();
|
|
323
|
+
}
|
|
324
|
+
return defaultChecker;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Quick brand compliance check
|
|
328
|
+
*/
|
|
329
|
+
export function checkBrandCompliance(text, sentiment = 'neutral') {
|
|
330
|
+
return getDefaultChecker().check(text, sentiment);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Validate response before sending
|
|
334
|
+
*/
|
|
335
|
+
export function validateResponseForBrand(responseText, sentiment = 'neutral') {
|
|
336
|
+
return getDefaultChecker().validateResponse(responseText, sentiment);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Perform pre-send brand test on response
|
|
340
|
+
* Throws BrandComplianceError if validation fails
|
|
341
|
+
*/
|
|
342
|
+
export function performBrandTest(responseText, options) {
|
|
343
|
+
if (!config.brandCompliance.enabled || !config.brandCompliance.preSendValidation) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const result = validateResponseForBrand(responseText, options?.sentiment ?? 'neutral');
|
|
347
|
+
if (result.complianceCheck.forbiddenTermsResult.hasForbiddenTerms) {
|
|
348
|
+
throw new ForbiddenTermsDetectedError(result.complianceCheck.forbiddenTermsResult.detectedTerms, 'generated_response', {
|
|
349
|
+
conversationId: options?.conversationId,
|
|
350
|
+
messageId: options?.messageId,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (!result.canBeSent) {
|
|
354
|
+
throw new BrandComplianceError(`Response failed brand compliance check: ${result.errors.join('; ')}`, 'pre_send_validation_failed', {
|
|
355
|
+
complianceScore: result.complianceCheck.score,
|
|
356
|
+
conversationId: options?.conversationId,
|
|
357
|
+
messageId: options?.messageId,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get brand voice guidelines for a sentiment
|
|
363
|
+
*/
|
|
364
|
+
export function getBrandVoiceGuidelines(sentiment) {
|
|
365
|
+
return BRAND_VOICE_GUIDELINES[sentiment];
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Apply terminology corrections to improve brand compliance
|
|
369
|
+
*/
|
|
370
|
+
export function applyBrandTerminologyCorrections(text) {
|
|
371
|
+
return getDefaultChecker().getSuggestedImprovements(text);
|
|
372
|
+
}
|
|
373
|
+
// =============================================================================
|
|
374
|
+
// Exports for Brand Module
|
|
375
|
+
// =============================================================================
|
|
376
|
+
export { ForbiddenTermsDetector } from './forbidden-terms.js';
|
|
377
|
+
export { scanForForbiddenTerms, containsForbiddenTerms, scanMessageContent, createComplianceStatusFromScan, requiresEscalationForForbiddenTerms, } from './forbidden-terms.js';
|
|
378
|
+
//# sourceMappingURL=compliance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../../src/brand/compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forbidden Terms Detector
|
|
3
|
+
*
|
|
4
|
+
* Scans text for marketplace-specific terminology that requires escalation.
|
|
5
|
+
* This is a critical component for maintaining Catalist's brand positioning
|
|
6
|
+
* as an "AI-native B2B marketplace" (NOT a wholesale distributor).
|
|
7
|
+
*
|
|
8
|
+
* CRITICAL: Any message containing forbidden terms MUST be escalated to humans.
|
|
9
|
+
* The agent cannot autonomously respond to these messages.
|
|
10
|
+
*/
|
|
11
|
+
import type { BrandComplianceStatus } from '../types.js';
|
|
12
|
+
export declare class ForbiddenTermsDetector {
|
|
13
|
+
private patterns;
|
|
14
|
+
private terms;
|
|
15
|
+
private termPatternMap;
|
|
16
|
+
constructor(customTerms?: string[]);
|
|
17
|
+
/**
|
|
18
|
+
* Build a regex pattern for a term that handles:
|
|
19
|
+
* - Word boundaries
|
|
20
|
+
* - Case insensitivity
|
|
21
|
+
* - Common variations (plurals, etc.)
|
|
22
|
+
* - Special characters in terms
|
|
23
|
+
*/
|
|
24
|
+
private buildPattern;
|
|
25
|
+
/**
|
|
26
|
+
* Scan text for forbidden terms
|
|
27
|
+
* Returns array of detected terms (empty if none found)
|
|
28
|
+
*/
|
|
29
|
+
scan(text: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Quick check if text contains any forbidden terms
|
|
32
|
+
*/
|
|
33
|
+
containsForbiddenTerms(text: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get detailed scan results with positions
|
|
36
|
+
*/
|
|
37
|
+
scanWithPositions(text: string): ForbiddenTermMatch[];
|
|
38
|
+
/**
|
|
39
|
+
* Normalize text for consistent matching
|
|
40
|
+
*/
|
|
41
|
+
private normalizeText;
|
|
42
|
+
/**
|
|
43
|
+
* Extract surrounding context for a match
|
|
44
|
+
*/
|
|
45
|
+
private extractContext;
|
|
46
|
+
/**
|
|
47
|
+
* Add additional terms at runtime
|
|
48
|
+
*/
|
|
49
|
+
addTerms(terms: string[]): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get all registered forbidden terms
|
|
52
|
+
*/
|
|
53
|
+
getTerms(): string[];
|
|
54
|
+
}
|
|
55
|
+
export interface ForbiddenTermMatch {
|
|
56
|
+
term: string;
|
|
57
|
+
matchedText: string;
|
|
58
|
+
position: number;
|
|
59
|
+
context: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ForbiddenTermsScanResult {
|
|
62
|
+
hasForbiddenTerms: boolean;
|
|
63
|
+
detectedTerms: string[];
|
|
64
|
+
matches: ForbiddenTermMatch[];
|
|
65
|
+
scannedAt: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the default forbidden terms detector (singleton)
|
|
69
|
+
*/
|
|
70
|
+
export declare function getDefaultDetector(): ForbiddenTermsDetector;
|
|
71
|
+
/**
|
|
72
|
+
* Quick check if text contains forbidden terms
|
|
73
|
+
*/
|
|
74
|
+
export declare function containsForbiddenTerms(text: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Scan text for forbidden terms and return all detected terms
|
|
77
|
+
*/
|
|
78
|
+
export declare function scanForForbiddenTerms(text: string): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Get detailed scan results
|
|
81
|
+
*/
|
|
82
|
+
export declare function scanForForbiddenTermsDetailed(text: string): ForbiddenTermsScanResult;
|
|
83
|
+
/**
|
|
84
|
+
* Scan message content (handles both plain text and HTML)
|
|
85
|
+
*/
|
|
86
|
+
export declare function scanMessageContent(content: {
|
|
87
|
+
text?: string;
|
|
88
|
+
html?: string;
|
|
89
|
+
subject?: string;
|
|
90
|
+
}): ForbiddenTermsScanResult;
|
|
91
|
+
/**
|
|
92
|
+
* Create brand compliance status from scan result
|
|
93
|
+
*/
|
|
94
|
+
export declare function createComplianceStatusFromScan(scanResult: ForbiddenTermsScanResult): BrandComplianceStatus;
|
|
95
|
+
/**
|
|
96
|
+
* Check if escalation is required based on forbidden terms
|
|
97
|
+
*/
|
|
98
|
+
export declare function requiresEscalationForForbiddenTerms(text: string): boolean;
|
|
99
|
+
//# sourceMappingURL=forbidden-terms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forbidden-terms.d.ts","sourceRoot":"","sources":["../../src/brand/forbidden-terms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAMzD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,cAAc,CAAsB;gBAEhC,WAAW,CAAC,EAAE,MAAM,EAAE;IAalC;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAiBpB;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAoB5B;;OAEG;IACH,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAiB7C;;OAEG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAyBrD;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAiBtB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAW/B;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;CAGrB;AAMD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AASD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,sBAAsB,CAK3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,CAUpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,wBAAwB,CA6B3B;AAoBD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,wBAAwB,GACnC,qBAAqB,CAgBvB;AAED;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKzE"}
|