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,351 @@
1
+ /**
2
+ * Sentiment Analysis Service
3
+ *
4
+ * Analyzes message sentiment and urgency using Claude.
5
+ * Determines customer emotional state and time-sensitivity of request.
6
+ */
7
+ import Anthropic from '@anthropic-ai/sdk';
8
+ import { config } from '../config.js';
9
+ import { AnalysisError } from '../errors.js';
10
+ // =============================================================================
11
+ // Urgency Signal Keywords
12
+ // =============================================================================
13
+ const URGENCY_KEYWORDS = {
14
+ critical: [
15
+ 'urgent',
16
+ 'emergency',
17
+ 'asap',
18
+ 'immediately',
19
+ 'right now',
20
+ 'critical',
21
+ 'desperately',
22
+ 'crisis',
23
+ ],
24
+ high: [
25
+ 'quickly',
26
+ 'soon as possible',
27
+ 'priority',
28
+ 'important',
29
+ 'need this today',
30
+ 'deadline',
31
+ 'time sensitive',
32
+ 'rush',
33
+ ],
34
+ medium: ['when you can', 'appreciate', 'would like', 'please help', 'waiting', 'checking in'],
35
+ low: ['whenever', 'no rush', 'when convenient', 'just wondering', 'curious'],
36
+ };
37
+ // =============================================================================
38
+ // Sentiment Analysis Prompt
39
+ // =============================================================================
40
+ const SENTIMENT_ANALYSIS_PROMPT = `You are a sentiment and urgency analysis system for customer support messages.
41
+
42
+ Your task is to analyze:
43
+ 1. **Sentiment**: The emotional tone of the message
44
+ 2. **Urgency**: How time-sensitive the request is
45
+
46
+ ## Sentiment Categories
47
+ - **positive**: Happy, satisfied, grateful, enthusiastic
48
+ - **neutral**: Matter-of-fact, informational, no strong emotion
49
+ - **negative**: Frustrated, disappointed, angry, upset
50
+
51
+ ## Urgency Levels
52
+ - **critical**: Immediate action required, business-stopping issue
53
+ - **high**: Needs attention soon, deadline mentioned
54
+ - **medium**: Standard request, no specific timeline
55
+ - **low**: No urgency indicated, casual inquiry
56
+
57
+ ## Response Format
58
+
59
+ Respond with a JSON object in this exact format:
60
+ {
61
+ "category": "positive|neutral|negative",
62
+ "score": 0.0 to 1.0 for positive, -1.0 to 0.0 for negative, around 0.0 for neutral,
63
+ "urgency": "critical|high|medium|low",
64
+ "urgency_signals": ["list of phrases indicating urgency"],
65
+ "emotion_indicators": ["list of emotional phrases detected"]
66
+ }
67
+
68
+ ## Important Notes
69
+
70
+ - Score ranges: positive (0.3 to 1.0), neutral (-0.3 to 0.3), negative (-1.0 to -0.3)
71
+ - Consider context: a "thank you" after a complaint is still likely overall negative
72
+ - ALL CAPS, multiple exclamation marks, or profanity increase urgency/negativity
73
+ - Questions are typically neutral unless accompanied by frustration cues
74
+ `;
75
+ // =============================================================================
76
+ // Sentiment Analysis Service
77
+ // =============================================================================
78
+ export class SentimentAnalysisService {
79
+ client = null;
80
+ getClient() {
81
+ if (!this.client) {
82
+ if (config.claude.apiKey) {
83
+ this.client = new Anthropic({
84
+ apiKey: config.claude.apiKey,
85
+ });
86
+ }
87
+ else {
88
+ throw new AnalysisError('Claude API key not configured', 'sentiment', {
89
+ context: { reason: 'Missing ANTHROPIC_API_KEY' },
90
+ });
91
+ }
92
+ }
93
+ return this.client;
94
+ }
95
+ /**
96
+ * Analyze sentiment and urgency of a message
97
+ */
98
+ async analyze(message) {
99
+ try {
100
+ const client = this.getClient();
101
+ const content = message.content.text;
102
+ const response = await client.messages.create({
103
+ model: config.claude.model,
104
+ max_tokens: 256,
105
+ system: SENTIMENT_ANALYSIS_PROMPT,
106
+ messages: [
107
+ {
108
+ role: 'user',
109
+ content: `Analyze the sentiment and urgency of this customer message:\n\n${content}`,
110
+ },
111
+ ],
112
+ });
113
+ const textContent = response.content.find((c) => c.type === 'text');
114
+ if (!textContent || textContent.type !== 'text') {
115
+ throw new AnalysisError('No text response from Claude', 'sentiment');
116
+ }
117
+ return this.parseSentimentResponse(textContent.text);
118
+ }
119
+ catch (error) {
120
+ if (error instanceof AnalysisError) {
121
+ throw error;
122
+ }
123
+ throw new AnalysisError(`Sentiment analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'sentiment', {
124
+ cause: error instanceof Error ? error : undefined,
125
+ messageId: message.id,
126
+ });
127
+ }
128
+ }
129
+ /**
130
+ * Parse the sentiment response from Claude
131
+ */
132
+ parseSentimentResponse(text) {
133
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
134
+ if (!jsonMatch) {
135
+ throw new AnalysisError('Could not parse sentiment analysis JSON', 'sentiment', {
136
+ context: { response: text.substring(0, 200) },
137
+ });
138
+ }
139
+ try {
140
+ const parsed = JSON.parse(jsonMatch[0]);
141
+ const category = this.validateSentimentCategory(parsed.category);
142
+ const urgency = this.validateUrgencyLevel(parsed.urgency);
143
+ const score = this.normalizeScore(parsed.score, category);
144
+ return {
145
+ category,
146
+ score,
147
+ urgency,
148
+ urgencySignals: parsed.urgency_signals ?? [],
149
+ };
150
+ }
151
+ catch {
152
+ throw new AnalysisError('Invalid JSON in sentiment analysis response', 'sentiment', {
153
+ context: { response: text.substring(0, 200) },
154
+ });
155
+ }
156
+ }
157
+ /**
158
+ * Validate sentiment category
159
+ */
160
+ validateSentimentCategory(category) {
161
+ if (category === 'positive' || category === 'neutral' || category === 'negative') {
162
+ return category;
163
+ }
164
+ return 'neutral';
165
+ }
166
+ /**
167
+ * Validate urgency level
168
+ */
169
+ validateUrgencyLevel(urgency) {
170
+ if (urgency === 'critical' ||
171
+ urgency === 'high' ||
172
+ urgency === 'medium' ||
173
+ urgency === 'low') {
174
+ return urgency;
175
+ }
176
+ return 'medium';
177
+ }
178
+ /**
179
+ * Normalize score to expected range
180
+ */
181
+ normalizeScore(score, category) {
182
+ if (typeof score !== 'number' || isNaN(score)) {
183
+ // Default scores based on category
184
+ switch (category) {
185
+ case 'positive':
186
+ return 0.5;
187
+ case 'negative':
188
+ return -0.5;
189
+ default:
190
+ return 0;
191
+ }
192
+ }
193
+ return Math.max(-1, Math.min(1, score));
194
+ }
195
+ /**
196
+ * Analyze sentiment using heuristics (fallback)
197
+ */
198
+ analyzeWithHeuristics(message) {
199
+ const text = message.content.text.toLowerCase();
200
+ // Sentiment indicators
201
+ const positiveWords = [
202
+ 'thank',
203
+ 'thanks',
204
+ 'great',
205
+ 'awesome',
206
+ 'excellent',
207
+ 'appreciate',
208
+ 'love',
209
+ 'perfect',
210
+ 'wonderful',
211
+ ];
212
+ const negativeWords = [
213
+ 'frustrated',
214
+ 'disappointed',
215
+ 'angry',
216
+ 'upset',
217
+ 'terrible',
218
+ 'awful',
219
+ 'horrible',
220
+ 'unacceptable',
221
+ 'problem',
222
+ 'issue',
223
+ 'complaint',
224
+ 'wrong',
225
+ ];
226
+ let positiveScore = 0;
227
+ let negativeScore = 0;
228
+ for (const word of positiveWords) {
229
+ if (text.includes(word))
230
+ positiveScore++;
231
+ }
232
+ for (const word of negativeWords) {
233
+ if (text.includes(word))
234
+ negativeScore++;
235
+ }
236
+ // Check for emphatic indicators
237
+ const hasAllCaps = /[A-Z]{4,}/.test(message.content.text);
238
+ const hasMultipleExclamation = /!{2,}/.test(message.content.text);
239
+ if (hasAllCaps || hasMultipleExclamation) {
240
+ negativeScore += 1;
241
+ }
242
+ // Determine category and score
243
+ let category;
244
+ let score;
245
+ if (negativeScore > positiveScore) {
246
+ category = 'negative';
247
+ score = -0.3 - negativeScore * 0.15;
248
+ }
249
+ else if (positiveScore > negativeScore) {
250
+ category = 'positive';
251
+ score = 0.3 + positiveScore * 0.15;
252
+ }
253
+ else {
254
+ category = 'neutral';
255
+ score = 0;
256
+ }
257
+ score = Math.max(-1, Math.min(1, score));
258
+ // Detect urgency
259
+ const urgencySignals = [];
260
+ let urgency = 'medium';
261
+ for (const [level, keywords] of Object.entries(URGENCY_KEYWORDS)) {
262
+ for (const keyword of keywords) {
263
+ if (text.includes(keyword)) {
264
+ urgencySignals.push(keyword);
265
+ if (level === 'critical' ||
266
+ (level === 'high' && urgency !== 'critical') ||
267
+ (level === 'low' && urgency === 'medium')) {
268
+ urgency = level;
269
+ }
270
+ }
271
+ }
272
+ }
273
+ return {
274
+ category,
275
+ score,
276
+ urgency,
277
+ urgencySignals,
278
+ };
279
+ }
280
+ }
281
+ // =============================================================================
282
+ // Singleton and Utility Functions
283
+ // =============================================================================
284
+ let sentimentService = null;
285
+ export function getSentimentAnalysisService() {
286
+ if (!sentimentService) {
287
+ sentimentService = new SentimentAnalysisService();
288
+ }
289
+ return sentimentService;
290
+ }
291
+ /**
292
+ * Analyze message sentiment
293
+ */
294
+ export async function analyzeSentiment(message) {
295
+ return getSentimentAnalysisService().analyze(message);
296
+ }
297
+ /**
298
+ * Analyze sentiment using heuristics (fallback)
299
+ */
300
+ export function analyzeSentimentHeuristic(message) {
301
+ return getSentimentAnalysisService().analyzeWithHeuristics(message);
302
+ }
303
+ /**
304
+ * Check if sentiment indicates escalation should be considered
305
+ */
306
+ export function shouldConsiderEscalationBySentiment(sentiment) {
307
+ // Escalate if:
308
+ // - Negative sentiment with strong negativity (score < -0.6)
309
+ // - Critical urgency
310
+ // - High urgency combined with negative sentiment
311
+ if (sentiment.urgency === 'critical') {
312
+ return true;
313
+ }
314
+ if (sentiment.category === 'negative' && sentiment.score < -0.6) {
315
+ return true;
316
+ }
317
+ if (sentiment.urgency === 'high' && sentiment.category === 'negative') {
318
+ return true;
319
+ }
320
+ return false;
321
+ }
322
+ /**
323
+ * Get urgency score (0-1) for ranking
324
+ */
325
+ export function getUrgencyScore(urgency) {
326
+ switch (urgency) {
327
+ case 'critical':
328
+ return 1.0;
329
+ case 'high':
330
+ return 0.75;
331
+ case 'medium':
332
+ return 0.5;
333
+ case 'low':
334
+ return 0.25;
335
+ default:
336
+ return 0.5;
337
+ }
338
+ }
339
+ /**
340
+ * Combine urgency from multiple sources
341
+ */
342
+ export function combineUrgency(levels) {
343
+ if (levels.includes('critical'))
344
+ return 'critical';
345
+ if (levels.includes('high'))
346
+ return 'high';
347
+ if (levels.includes('medium'))
348
+ return 'medium';
349
+ return 'low';
350
+ }
351
+ //# sourceMappingURL=sentiment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentiment.js","sourceRoot":"","sources":["../../src/analysis/sentiment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
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 { type ForbiddenTermsScanResult } from './forbidden-terms.js';
13
+ import type { BrandComplianceStatus, SentimentCategory } from '../types.js';
14
+ export declare class BrandTerminologyEnforcer {
15
+ private preferredTerms;
16
+ private vendorPhrasePatterns;
17
+ constructor();
18
+ private escapeRegex;
19
+ /**
20
+ * Check if text contains vendor-style positioning
21
+ */
22
+ containsVendorStyleLanguage(text: string): {
23
+ found: boolean;
24
+ phrases: string[];
25
+ };
26
+ /**
27
+ * Suggest corrections for non-preferred terminology
28
+ */
29
+ suggestCorrections(text: string): TerminologyCorrection[];
30
+ /**
31
+ * Apply terminology corrections to text
32
+ */
33
+ applyCorrections(text: string): string;
34
+ }
35
+ export interface TerminologyCorrection {
36
+ original: string;
37
+ suggested: string;
38
+ reason: string;
39
+ }
40
+ export interface BrandComplianceCheckResult {
41
+ passed: boolean;
42
+ score: number;
43
+ forbiddenTermsResult: ForbiddenTermsScanResult;
44
+ vendorStyleCheck: {
45
+ found: boolean;
46
+ phrases: string[];
47
+ };
48
+ terminologyCorrections: TerminologyCorrection[];
49
+ toneIssues: string[];
50
+ overallStatus: BrandComplianceStatus;
51
+ checkedAt: string;
52
+ }
53
+ export interface ResponseValidationResult {
54
+ isValid: boolean;
55
+ complianceCheck: BrandComplianceCheckResult;
56
+ errors: string[];
57
+ warnings: string[];
58
+ canBeSent: boolean;
59
+ requiresHumanReview: boolean;
60
+ }
61
+ export declare class BrandComplianceChecker {
62
+ private forbiddenTermsDetector;
63
+ private terminologyEnforcer;
64
+ constructor();
65
+ /**
66
+ * Perform comprehensive brand compliance check on text
67
+ */
68
+ check(text: string, sentiment?: SentimentCategory): BrandComplianceCheckResult;
69
+ /**
70
+ * Check for tone issues based on sentiment context
71
+ */
72
+ private checkToneIssues;
73
+ /**
74
+ * Validate a generated response before sending
75
+ */
76
+ validateResponse(responseText: string, sentiment?: SentimentCategory): ResponseValidationResult;
77
+ /**
78
+ * Get suggested improvements for a response
79
+ */
80
+ getSuggestedImprovements(responseText: string): string;
81
+ }
82
+ export declare function getDefaultChecker(): BrandComplianceChecker;
83
+ /**
84
+ * Quick brand compliance check
85
+ */
86
+ export declare function checkBrandCompliance(text: string, sentiment?: SentimentCategory): BrandComplianceCheckResult;
87
+ /**
88
+ * Validate response before sending
89
+ */
90
+ export declare function validateResponseForBrand(responseText: string, sentiment?: SentimentCategory): ResponseValidationResult;
91
+ /**
92
+ * Perform pre-send brand test on response
93
+ * Throws BrandComplianceError if validation fails
94
+ */
95
+ export declare function performBrandTest(responseText: string, options?: {
96
+ sentiment?: SentimentCategory;
97
+ conversationId?: string;
98
+ messageId?: string;
99
+ }): void;
100
+ /**
101
+ * Get brand voice guidelines for a sentiment
102
+ */
103
+ export declare function getBrandVoiceGuidelines(sentiment: SentimentCategory): {
104
+ readonly tone: "warm, appreciative, professional";
105
+ readonly avoid: readonly ["overly casual", "excessive exclamation marks", "slang"];
106
+ readonly emphasis: readonly ["gratitude", "partnership", "continued support"];
107
+ } | {
108
+ readonly tone: "professional, helpful, clear";
109
+ readonly avoid: readonly ["overly formal", "jargon", "condescending"];
110
+ readonly emphasis: readonly ["clarity", "efficiency", "value"];
111
+ } | {
112
+ readonly tone: "empathetic, solution-focused, patient";
113
+ readonly avoid: readonly ["defensive", "dismissive", "blame-shifting"];
114
+ readonly emphasis: readonly ["acknowledgment", "accountability", "resolution"];
115
+ };
116
+ /**
117
+ * Apply terminology corrections to improve brand compliance
118
+ */
119
+ export declare function applyBrandTerminologyCorrections(text: string): string;
120
+ export { ForbiddenTermsDetector } from './forbidden-terms.js';
121
+ export { scanForForbiddenTerms, containsForbiddenTerms, scanMessageContent, createComplianceStatusFromScan, requiresEscalationForForbiddenTerms, } from './forbidden-terms.js';
122
+ //# sourceMappingURL=compliance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/brand/compliance.ts"],"names":[],"mappings":"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"}