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,641 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Generation Module
|
|
3
|
+
*
|
|
4
|
+
* Generates brand-compliant responses using Claude:
|
|
5
|
+
* - Assembles context from analysis and knowledge
|
|
6
|
+
* - Applies brand voice guidelines
|
|
7
|
+
* - Enforces forbidden terms rules
|
|
8
|
+
* - Formats for target channel
|
|
9
|
+
* - Validates before sending
|
|
10
|
+
*/
|
|
11
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
12
|
+
import { config } from '../config.js';
|
|
13
|
+
import { GenerationError, ResponseQualityError, ForbiddenTermsDetectedError } from '../errors.js';
|
|
14
|
+
import { validateResponseForBrand, applyBrandTerminologyCorrections, getBrandVoiceGuidelines, } from '../brand/index.js';
|
|
15
|
+
import { createResponseId } from '../types.js';
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// System Prompt
|
|
18
|
+
// =============================================================================
|
|
19
|
+
const SYSTEM_PROMPT = `You are a customer support agent for Catalist, an AI-native B2B marketplace platform.
|
|
20
|
+
|
|
21
|
+
## Your Identity
|
|
22
|
+
- You represent Catalist, a modern B2B marketplace (NOT a wholesale distributor)
|
|
23
|
+
- You are professional, direct, and helpful
|
|
24
|
+
- Keep responses concise - say what needs to be said, nothing more
|
|
25
|
+
|
|
26
|
+
## CRITICAL: Use Provided Customer Context
|
|
27
|
+
|
|
28
|
+
When customer information is provided in the context (from sender email lookup):
|
|
29
|
+
- DO NOT ask for account details, company name, or email - we already have it
|
|
30
|
+
- Address them by name if available
|
|
31
|
+
- Use this information to personalize your response
|
|
32
|
+
|
|
33
|
+
Only ask for account details if NO customer information appears in the context.
|
|
34
|
+
|
|
35
|
+
## CRITICAL: Pricing Policy - NO DISCOUNTS
|
|
36
|
+
|
|
37
|
+
Catalist does NOT offer discounts, volume pricing, or special pricing arrangements.
|
|
38
|
+
- Prices are set by our brand partners and are non-negotiable
|
|
39
|
+
- The listed price reflects our best available rate for all quantities
|
|
40
|
+
- Do NOT mention "working on pricing" or imply flexibility
|
|
41
|
+
|
|
42
|
+
Example response to discount requests:
|
|
43
|
+
"Our marketplace prices are set by our brand partners and are non-negotiable. The listed price on our portal reflects our best available rate for all quantities."
|
|
44
|
+
|
|
45
|
+
## Self-Service: Marketplace Ungating Tool
|
|
46
|
+
|
|
47
|
+
For Amazon/Walmart ungating questions, direct customers to: https://b2b.catalistgroup.co/ungating
|
|
48
|
+
|
|
49
|
+
The workflow is: get approved for the brand through the ungating tool first, then place your order through our portal at https://b2b.catalistgroup.co
|
|
50
|
+
|
|
51
|
+
The tool provides everything you need:
|
|
52
|
+
- Professional invoices from Catalist formatted for Amazon requirements
|
|
53
|
+
- AI guidance with success probability estimates for the specific brand
|
|
54
|
+
- Pre-written case templates to copy into Seller Central
|
|
55
|
+
- Step-by-step submission instructions
|
|
56
|
+
- Resubmission strategies for handling denials
|
|
57
|
+
|
|
58
|
+
Quick note on denials: They're normal (40-60% success on first try, but 85-95% success by the third attempt). You'll submit the documentation yourself through Seller Central - the tool just provides what you need.
|
|
59
|
+
|
|
60
|
+
## CRITICAL: Brand Terminology Rules
|
|
61
|
+
|
|
62
|
+
NEVER facilitate these requests (escalate to human):
|
|
63
|
+
- Invoice manipulation (editing, modifying, or falsifying invoices)
|
|
64
|
+
- Competitor price matching requests
|
|
65
|
+
|
|
66
|
+
IMPORTANT: Our clients ARE Amazon FBA sellers. The following terms are ALLOWED:
|
|
67
|
+
- Amazon, FBA, FBM, Seller Central, ASIN, Buy Box
|
|
68
|
+
- Walmart, Walmart Marketplace, WFS
|
|
69
|
+
- eBay, or any other marketplace platforms
|
|
70
|
+
- Ungating, brand approval, category approval
|
|
71
|
+
- Reseller, reselling, arbitrage
|
|
72
|
+
|
|
73
|
+
Use correct terminology:
|
|
74
|
+
- "Catalist" (NEVER "Catalist Group" in body text)
|
|
75
|
+
- "B2B marketplace" (not "wholesale distributor")
|
|
76
|
+
- "Brand partners" (not "vendors")
|
|
77
|
+
|
|
78
|
+
## Brand/Product Sourcing & Catalog Requests
|
|
79
|
+
|
|
80
|
+
When customers ask for brand suggestions, help finding products, or catalog access:
|
|
81
|
+
- Direct them to LOG IN to our marketplace at https://b2b.catalistgroup.co
|
|
82
|
+
- NEVER say "create an account" - assume they already have one (they're emailing us!)
|
|
83
|
+
- Mention they can filter by category, brand, or search for specific products
|
|
84
|
+
- We carry 1200+ brands across categories like home & kitchen, sports and outdoors, hardware, etc.
|
|
85
|
+
|
|
86
|
+
Example response:
|
|
87
|
+
"You can browse our full catalog by logging into the portal at https://b2b.catalistgroup.co where you can filter by category or search for specific products. We carry 1200+ brands across categories like home & kitchen, sports and outdoors, hardware, and more."
|
|
88
|
+
|
|
89
|
+
## CSV Catalog Downloads - YES WE OFFER THIS
|
|
90
|
+
|
|
91
|
+
IMPORTANT: We DO provide CSV catalog downloads. Customers can:
|
|
92
|
+
1. Log in to the portal at https://b2b.catalistgroup.co
|
|
93
|
+
2. Click the "Download CSV" button on the Products page (next to the search bar)
|
|
94
|
+
3. Export the current filtered product list as a CSV file
|
|
95
|
+
|
|
96
|
+
When customers ask about CSV downloads, catalog exports, spreadsheets, or product data files:
|
|
97
|
+
- Confirm YES, we offer CSV downloads
|
|
98
|
+
- Direct them to log in and use the "Download CSV" button
|
|
99
|
+
- Mention they can apply filters first to export a specific subset of products
|
|
100
|
+
|
|
101
|
+
Example response for CSV/catalog download requests:
|
|
102
|
+
"Yes, you can download our product catalog as a CSV file. Just log in to the portal at https://b2b.catalistgroup.co, apply any filters you want (by brand, category, etc.), and click the 'Download CSV' button next to the search bar. The export will include all products matching your current filters."
|
|
103
|
+
|
|
104
|
+
## Portal URL
|
|
105
|
+
|
|
106
|
+
Always use: https://b2b.catalistgroup.co
|
|
107
|
+
Never use "portal.catalistgroup.co" - this URL does not exist.
|
|
108
|
+
|
|
109
|
+
## Email Structure
|
|
110
|
+
|
|
111
|
+
Follow this structure for responses:
|
|
112
|
+
|
|
113
|
+
1. Brief greeting with customer name
|
|
114
|
+
2. Direct answer to their question (no preamble)
|
|
115
|
+
3. If ungating: explain the tool with bullet list, then workflow
|
|
116
|
+
4. Quick note for secondary info (denial rates, etc.)
|
|
117
|
+
5. Offer to help with next steps
|
|
118
|
+
6. Sign off with "Best," and your name
|
|
119
|
+
|
|
120
|
+
Example closing:
|
|
121
|
+
"Let me know if you have any questions about getting started with either the ungating process or placing your order.
|
|
122
|
+
|
|
123
|
+
Best,
|
|
124
|
+
[Name]"
|
|
125
|
+
|
|
126
|
+
## Email Formatting (IMPORTANT)
|
|
127
|
+
|
|
128
|
+
- Use PLAIN TEXT only - no Markdown formatting
|
|
129
|
+
- Do NOT use asterisks for bold (**text**) or italics (*text*)
|
|
130
|
+
- Do NOT use hashtags for headers (## Header)
|
|
131
|
+
- Use dashes (- item) for bullet lists
|
|
132
|
+
- Indent bullet lists with two spaces for visual clarity
|
|
133
|
+
- Keep URLs on their own line when possible
|
|
134
|
+
- Do NOT include signature block - it's added automatically
|
|
135
|
+
|
|
136
|
+
## CRITICAL: Write Like a Human, Not an AI
|
|
137
|
+
|
|
138
|
+
Words and phrases to NEVER use:
|
|
139
|
+
- "I hope this helps" / "Let me know if you need anything else" (generic)
|
|
140
|
+
- "Additionally" / "Moreover" / "Furthermore"
|
|
141
|
+
- "Delve" / "Navigate" / "Landscape"
|
|
142
|
+
- "Crucial" / "Pivotal" / "Key" (as adjectives)
|
|
143
|
+
- "Seamless" / "Robust"
|
|
144
|
+
- "Testament to" / "Serves as"
|
|
145
|
+
- "I understand your concern" (just address it)
|
|
146
|
+
- "Great question!" / "Absolutely!" / "Certainly!"
|
|
147
|
+
- "reaching out" (just say "your interest" or "your email")
|
|
148
|
+
|
|
149
|
+
Patterns to avoid:
|
|
150
|
+
- Em dashes for dramatic effect—like this—everywhere
|
|
151
|
+
- Rule of three lists (fast, efficient, and reliable)
|
|
152
|
+
- "It's not just X, it's Y" constructions
|
|
153
|
+
- Starting with "I" repeatedly
|
|
154
|
+
- Excessive hedging ("might potentially be able to")
|
|
155
|
+
- Long explanatory intros before the actual answer
|
|
156
|
+
|
|
157
|
+
Instead:
|
|
158
|
+
- Be direct: answer first, explain second
|
|
159
|
+
- Use simple words: "is" instead of "serves as"
|
|
160
|
+
- Use contractions (we're, you'll, that's)
|
|
161
|
+
- Use "Quick note:" for secondary information
|
|
162
|
+
- Keep sentences short and scannable
|
|
163
|
+
`;
|
|
164
|
+
// =============================================================================
|
|
165
|
+
// Response Generation Service
|
|
166
|
+
// =============================================================================
|
|
167
|
+
export class ResponseGenerationService {
|
|
168
|
+
client = null;
|
|
169
|
+
effectiveConfig;
|
|
170
|
+
constructor(configOverride) {
|
|
171
|
+
this.effectiveConfig = configOverride ?? config;
|
|
172
|
+
}
|
|
173
|
+
getClient() {
|
|
174
|
+
if (!this.client) {
|
|
175
|
+
if (this.effectiveConfig.claude.apiKey) {
|
|
176
|
+
this.client = new Anthropic({
|
|
177
|
+
apiKey: this.effectiveConfig.claude.apiKey,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
throw new GenerationError('Claude API key not configured', 'llm_call', {
|
|
182
|
+
context: { reason: 'Missing ANTHROPIC_API_KEY' },
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return this.client;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Generate a response for a message
|
|
190
|
+
*/
|
|
191
|
+
async generateResponse(message, analysis, knowledge, options = {}) {
|
|
192
|
+
const startTime = Date.now();
|
|
193
|
+
const targetChannel = options.targetChannel ?? message.channel;
|
|
194
|
+
const maxAttempts = options.maxAttempts ?? 3;
|
|
195
|
+
let lastError;
|
|
196
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
197
|
+
try {
|
|
198
|
+
// 1. Build the context prompt
|
|
199
|
+
const contextPrompt = this.buildContextPrompt(message, analysis, knowledge);
|
|
200
|
+
// 2. Generate response with Claude
|
|
201
|
+
const rawResponse = await this.callClaude(contextPrompt, analysis.sentiment.category);
|
|
202
|
+
// 3. Apply terminology corrections
|
|
203
|
+
let processedResponse = applyBrandTerminologyCorrections(rawResponse);
|
|
204
|
+
// 3.5. Humanize response - remove AI writing patterns
|
|
205
|
+
processedResponse = humanizeResponse(processedResponse);
|
|
206
|
+
// 4. Validate brand compliance
|
|
207
|
+
const validationResult = validateResponseForBrand(processedResponse, analysis.sentiment.category);
|
|
208
|
+
if (!validationResult.canBeSent) {
|
|
209
|
+
if (validationResult.complianceCheck.forbiddenTermsResult.hasForbiddenTerms) {
|
|
210
|
+
// This shouldn't happen with proper system prompt, but handle it
|
|
211
|
+
throw new ForbiddenTermsDetectedError(validationResult.complianceCheck.forbiddenTermsResult.detectedTerms, 'generated_response', { messageId: message.id, conversationId: message.conversationId });
|
|
212
|
+
}
|
|
213
|
+
// Try to fix non-critical issues
|
|
214
|
+
if (attempt < maxAttempts) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
throw new ResponseQualityError(validationResult.complianceCheck.score, validationResult.errors, { messageId: message.id, conversationId: message.conversationId });
|
|
218
|
+
}
|
|
219
|
+
// 5. Format for target channel
|
|
220
|
+
const formatting = this.formatForChannel(processedResponse, targetChannel, message.content.subject);
|
|
221
|
+
// 6. Extract citations
|
|
222
|
+
const citations = this.extractCitations(processedResponse, knowledge);
|
|
223
|
+
// 7. Calculate quality score
|
|
224
|
+
const qualityScore = this.calculateQualityScore(processedResponse, validationResult.complianceCheck.score, knowledge);
|
|
225
|
+
const latencyMs = Date.now() - startTime;
|
|
226
|
+
return {
|
|
227
|
+
id: createResponseId(`resp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`),
|
|
228
|
+
conversationId: analysis.conversationId,
|
|
229
|
+
messageId: message.id,
|
|
230
|
+
content: {
|
|
231
|
+
text: processedResponse,
|
|
232
|
+
html: formatting.email?.htmlBody,
|
|
233
|
+
subject: formatting.email?.subject,
|
|
234
|
+
},
|
|
235
|
+
formatting,
|
|
236
|
+
citations,
|
|
237
|
+
brandCompliance: validationResult.complianceCheck.overallStatus,
|
|
238
|
+
qualityScore,
|
|
239
|
+
generatedAt: new Date().toISOString(),
|
|
240
|
+
metadata: {
|
|
241
|
+
templateUsed: undefined,
|
|
242
|
+
modelUsed: this.effectiveConfig.claude.model,
|
|
243
|
+
tokensUsed: 0, // Would need to track from Claude response
|
|
244
|
+
latencyMs,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
250
|
+
if (error instanceof ForbiddenTermsDetectedError) {
|
|
251
|
+
// Don't retry forbidden terms - this is a critical failure
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
// Continue to next attempt
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
throw new GenerationError(`Response generation failed after ${maxAttempts} attempts: ${lastError?.message}`, 'llm_call', {
|
|
259
|
+
cause: lastError,
|
|
260
|
+
messageId: message.id,
|
|
261
|
+
conversationId: message.conversationId,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Build context prompt for Claude
|
|
266
|
+
*/
|
|
267
|
+
buildContextPrompt(message, analysis, knowledge) {
|
|
268
|
+
const sections = [];
|
|
269
|
+
// Customer context
|
|
270
|
+
if (knowledge.customer) {
|
|
271
|
+
sections.push(`## Customer Information
|
|
272
|
+
- Company: ${knowledge.customer.companyName}
|
|
273
|
+
- Contact: ${knowledge.customer.contactName || 'N/A'}
|
|
274
|
+
- Status: ${knowledge.customer.accountStatus}
|
|
275
|
+
${knowledge.customer.tier ? `- Tier: ${knowledge.customer.tier}` : ''}`);
|
|
276
|
+
}
|
|
277
|
+
// Analysis context
|
|
278
|
+
sections.push(`## Message Analysis
|
|
279
|
+
- Intent: ${analysis.intent.primary}${analysis.intent.secondary ? ` (secondary: ${analysis.intent.secondary})` : ''}
|
|
280
|
+
- Sentiment: ${analysis.sentiment.category} (score: ${analysis.sentiment.score.toFixed(2)})
|
|
281
|
+
- Urgency: ${analysis.sentiment.urgency}`);
|
|
282
|
+
// Order context
|
|
283
|
+
if (knowledge.orders && knowledge.orders.length > 0) {
|
|
284
|
+
const orderList = knowledge.orders
|
|
285
|
+
.slice(0, 3)
|
|
286
|
+
.map((o) => `- Order ${o.orderNumber}: ${o.status} (${o.totalAmount ? `$${o.totalAmount}` : 'N/A'})`)
|
|
287
|
+
.join('\n');
|
|
288
|
+
sections.push(`## Recent Orders\n${orderList}`);
|
|
289
|
+
}
|
|
290
|
+
// Resolved invoice context - prominently displayed so Claude knows not to ask for it
|
|
291
|
+
if (knowledge.resolvedInvoice) {
|
|
292
|
+
const inv = knowledge.resolvedInvoice.invoice;
|
|
293
|
+
const confidence = knowledge.resolvedInvoice.confidence;
|
|
294
|
+
const source = knowledge.resolvedInvoice.source;
|
|
295
|
+
let sourceExplanation = '';
|
|
296
|
+
if (source === 'extracted_number') {
|
|
297
|
+
sourceExplanation = 'Invoice number found in their message.';
|
|
298
|
+
}
|
|
299
|
+
else if (source === 'single_unpaid') {
|
|
300
|
+
sourceExplanation = 'This is their only unpaid invoice.';
|
|
301
|
+
}
|
|
302
|
+
else if (source === 'most_recent') {
|
|
303
|
+
sourceExplanation = 'This is their most recent invoice (no unpaid invoices).';
|
|
304
|
+
}
|
|
305
|
+
const statusDisplay = inv.status === 'issued' ? 'Unpaid' : inv.status === 'paid' ? 'Paid' : inv.status;
|
|
306
|
+
const issuedDate = inv.issuedAt ? new Date(inv.issuedAt).toLocaleDateString() : 'N/A';
|
|
307
|
+
const dueDate = inv.dueAt ? new Date(inv.dueAt).toLocaleDateString() : 'N/A';
|
|
308
|
+
const paidDate = inv.paidAt ? new Date(inv.paidAt).toLocaleDateString() : null;
|
|
309
|
+
sections.push(`## Identified Invoice
|
|
310
|
+
The customer is asking about this invoice (${confidence} confidence - ${sourceExplanation}):
|
|
311
|
+
- Invoice #: ${inv.invoiceNumber || inv.invoiceId}
|
|
312
|
+
- Amount: $${inv.total.toFixed(2)}
|
|
313
|
+
- Status: ${statusDisplay}
|
|
314
|
+
- Issued: ${issuedDate}
|
|
315
|
+
- Due: ${dueDate}${paidDate ? `\n- Paid: ${paidDate}` : ''}
|
|
316
|
+
|
|
317
|
+
IMPORTANT: Do NOT ask the customer for their invoice number - we have already identified it. Include the invoice number and key details in your response so they can confirm we're looking at the right one.`);
|
|
318
|
+
}
|
|
319
|
+
// Product context
|
|
320
|
+
if (knowledge.products && knowledge.products.length > 0) {
|
|
321
|
+
const productList = knowledge.products
|
|
322
|
+
.slice(0, 3)
|
|
323
|
+
.map((p) => `- ${p.name} (${p.sku}): ${p.availability}${p.price ? ` - $${p.price}` : ''}`)
|
|
324
|
+
.join('\n');
|
|
325
|
+
sections.push(`## Relevant Products\n${productList}`);
|
|
326
|
+
}
|
|
327
|
+
// Similar past conversations (few-shot examples)
|
|
328
|
+
if (knowledge.similarConversations && knowledge.similarConversations.length > 0) {
|
|
329
|
+
const examples = knowledge.similarConversations
|
|
330
|
+
.slice(0, 3) // Top 3 most similar
|
|
331
|
+
.map((conv, index) => {
|
|
332
|
+
const exampleParts = [
|
|
333
|
+
`### Example ${index + 1} (similarity: ${(conv.similarity * 100).toFixed(0)}%)`,
|
|
334
|
+
`**Customer Question:** ${conv.summary}`,
|
|
335
|
+
];
|
|
336
|
+
if (conv.successfulResponse) {
|
|
337
|
+
// Truncate long responses for context window efficiency
|
|
338
|
+
const responsePreview = conv.successfulResponse.length > 300
|
|
339
|
+
? conv.successfulResponse.substring(0, 300) + '...'
|
|
340
|
+
: conv.successfulResponse;
|
|
341
|
+
exampleParts.push(`**Successful Response:** ${responsePreview}`);
|
|
342
|
+
}
|
|
343
|
+
exampleParts.push(`**Outcome:** ${conv.resolution.replace(/_/g, ' ')}`);
|
|
344
|
+
return exampleParts.join('\n');
|
|
345
|
+
})
|
|
346
|
+
.join('\n\n');
|
|
347
|
+
sections.push(`## Similar Past Conversations (for reference)
|
|
348
|
+
The following are examples of similar questions we've successfully handled. Use these as reference for tone, structure, and approach:
|
|
349
|
+
|
|
350
|
+
${examples}
|
|
351
|
+
|
|
352
|
+
Note: Adapt these examples to the specific customer's situation rather than copying directly.`);
|
|
353
|
+
}
|
|
354
|
+
// Template suggestions (after similar conversations as they're more specific)
|
|
355
|
+
if (knowledge.templates && knowledge.templates.length > 0) {
|
|
356
|
+
const template = knowledge.templates[0];
|
|
357
|
+
if (template) {
|
|
358
|
+
sections.push(`## Suggested Template
|
|
359
|
+
Consider using elements from this approved template:
|
|
360
|
+
"${template.content.substring(0, 200)}..."`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Original message (always last for clear reference)
|
|
364
|
+
sections.push(`## Customer Message
|
|
365
|
+
${message.content.subject ? `Subject: ${message.content.subject}\n` : ''}${message.content.text}`);
|
|
366
|
+
return sections.join('\n\n');
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Call Claude to generate response
|
|
370
|
+
*/
|
|
371
|
+
async callClaude(contextPrompt, sentiment) {
|
|
372
|
+
const client = this.getClient();
|
|
373
|
+
// Add tone guidance based on sentiment
|
|
374
|
+
const voiceGuidelines = getBrandVoiceGuidelines(sentiment);
|
|
375
|
+
const toneInstruction = `\n\nTone for this response: ${voiceGuidelines.tone}`;
|
|
376
|
+
const response = await client.messages.create({
|
|
377
|
+
model: this.effectiveConfig.claude.model,
|
|
378
|
+
max_tokens: this.effectiveConfig.claude.maxTokens,
|
|
379
|
+
system: SYSTEM_PROMPT + toneInstruction,
|
|
380
|
+
messages: [
|
|
381
|
+
{
|
|
382
|
+
role: 'user',
|
|
383
|
+
content: `Based on the following context, write a helpful support response:\n\n${contextPrompt}`,
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
});
|
|
387
|
+
const textContent = response.content.find((c) => c.type === 'text');
|
|
388
|
+
if (!textContent || textContent.type !== 'text') {
|
|
389
|
+
throw new GenerationError('No text response from Claude', 'llm_call');
|
|
390
|
+
}
|
|
391
|
+
return textContent.text;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Format response for target channel
|
|
395
|
+
*/
|
|
396
|
+
formatForChannel(text, channel, originalSubject) {
|
|
397
|
+
const formatting = {};
|
|
398
|
+
switch (channel) {
|
|
399
|
+
case 'email':
|
|
400
|
+
formatting.email = {
|
|
401
|
+
subject: originalSubject ? `Re: ${originalSubject}` : 'Catalist Support',
|
|
402
|
+
htmlBody: this.formatAsHtml(text),
|
|
403
|
+
textBody: text,
|
|
404
|
+
};
|
|
405
|
+
break;
|
|
406
|
+
case 'sms':
|
|
407
|
+
// Truncate for SMS, keeping under 160 chars if possible
|
|
408
|
+
const smsText = this.formatForSms(text);
|
|
409
|
+
formatting.sms = {
|
|
410
|
+
body: smsText,
|
|
411
|
+
segments: Math.ceil(smsText.length / 160),
|
|
412
|
+
};
|
|
413
|
+
break;
|
|
414
|
+
case 'slack':
|
|
415
|
+
formatting.slack = {
|
|
416
|
+
blocks: this.formatAsSlackBlocks(text),
|
|
417
|
+
text: text,
|
|
418
|
+
};
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
return formatting;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Format text as HTML for email
|
|
425
|
+
*/
|
|
426
|
+
formatAsHtml(text) {
|
|
427
|
+
// Convert markdown-ish formatting to HTML
|
|
428
|
+
let html = text
|
|
429
|
+
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
|
430
|
+
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
|
|
431
|
+
.replace(/^- (.+)$/gm, '<li>$1</li>')
|
|
432
|
+
.replace(/\n\n/g, '</p><p>')
|
|
433
|
+
.replace(/\n/g, '<br>');
|
|
434
|
+
// Wrap in paragraph tags
|
|
435
|
+
html = `<p>${html}</p>`;
|
|
436
|
+
// Wrap list items
|
|
437
|
+
html = html.replace(/(<li>.*<\/li>)+/g, '<ul>$&</ul>');
|
|
438
|
+
return html;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Format text for SMS (truncate and simplify)
|
|
442
|
+
*/
|
|
443
|
+
formatForSms(text) {
|
|
444
|
+
// Remove formatting
|
|
445
|
+
let sms = text.replace(/\*\*?/g, '').replace(/^- /gm, '• ');
|
|
446
|
+
// Truncate if too long
|
|
447
|
+
if (sms.length > 320) {
|
|
448
|
+
// 2 SMS segments
|
|
449
|
+
sms = sms.substring(0, 317) + '...';
|
|
450
|
+
}
|
|
451
|
+
return sms;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Format text as Slack blocks
|
|
455
|
+
*/
|
|
456
|
+
formatAsSlackBlocks(text) {
|
|
457
|
+
// Convert to Slack mrkdwn format
|
|
458
|
+
const mrkdwn = text.replace(/\*\*([^*]+)\*\*/g, '*$1*');
|
|
459
|
+
return [
|
|
460
|
+
{
|
|
461
|
+
type: 'section',
|
|
462
|
+
text: {
|
|
463
|
+
type: 'mrkdwn',
|
|
464
|
+
text: mrkdwn,
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Extract citations from response
|
|
471
|
+
*/
|
|
472
|
+
extractCitations(text, knowledge) {
|
|
473
|
+
const citations = [];
|
|
474
|
+
// Extract order references
|
|
475
|
+
if (knowledge.orders) {
|
|
476
|
+
for (const order of knowledge.orders) {
|
|
477
|
+
if (text.includes(order.orderNumber)) {
|
|
478
|
+
citations.push({
|
|
479
|
+
type: 'order',
|
|
480
|
+
reference: order.orderNumber,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Extract product references
|
|
486
|
+
if (knowledge.products) {
|
|
487
|
+
for (const product of knowledge.products) {
|
|
488
|
+
if (text.includes(product.sku) || text.toLowerCase().includes(product.name.toLowerCase())) {
|
|
489
|
+
citations.push({
|
|
490
|
+
type: 'product',
|
|
491
|
+
reference: product.sku,
|
|
492
|
+
context: product.name,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return citations;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Calculate quality score for response
|
|
501
|
+
*/
|
|
502
|
+
calculateQualityScore(text, complianceScore, knowledge) {
|
|
503
|
+
let score = complianceScore / 100; // Start with compliance score
|
|
504
|
+
// Bonus for using available context
|
|
505
|
+
if (knowledge.customer && text.includes(knowledge.customer.companyName)) {
|
|
506
|
+
score += 0.05;
|
|
507
|
+
}
|
|
508
|
+
// Bonus for appropriate length (not too short, not too long)
|
|
509
|
+
const wordCount = text.split(/\s+/).length;
|
|
510
|
+
if (wordCount >= 30 && wordCount <= 200) {
|
|
511
|
+
score += 0.05;
|
|
512
|
+
}
|
|
513
|
+
// Cap at 1.0
|
|
514
|
+
return Math.min(1.0, Math.round(score * 100) / 100);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
// =============================================================================
|
|
518
|
+
// Humanization - Remove AI Writing Patterns
|
|
519
|
+
// =============================================================================
|
|
520
|
+
/**
|
|
521
|
+
* Remove common AI writing patterns to make responses sound more natural
|
|
522
|
+
* Based on Wikipedia's "Signs of AI writing" guide
|
|
523
|
+
*/
|
|
524
|
+
export function humanizeResponse(text) {
|
|
525
|
+
let result = text;
|
|
526
|
+
// Remove sycophantic/servile phrases
|
|
527
|
+
const sycophancyPatterns = [
|
|
528
|
+
/^(Great question!|Absolutely!|Certainly!|Of course!)\s*/gi,
|
|
529
|
+
/I hope this helps[.!]?\s*/gi,
|
|
530
|
+
/Let me know if you need anything else[.!]?\s*/gi,
|
|
531
|
+
/Please don't hesitate to reach out[.!]?\s*/gi,
|
|
532
|
+
/I'm happy to help[.!]?\s*/gi,
|
|
533
|
+
/I understand your concern[.!]?\s*/gi,
|
|
534
|
+
/Thank you for your patience[.!]?\s*/gi,
|
|
535
|
+
];
|
|
536
|
+
for (const pattern of sycophancyPatterns) {
|
|
537
|
+
result = result.replace(pattern, '');
|
|
538
|
+
}
|
|
539
|
+
// Brand name correction
|
|
540
|
+
result = result.replace(/Catalist/g, 'Catalist');
|
|
541
|
+
// Replace AI vocabulary words with simpler alternatives
|
|
542
|
+
const vocabularyReplacements = [
|
|
543
|
+
[/\bAdditionally\b/g, 'Also'],
|
|
544
|
+
[/\bMoreover\b/g, 'Also'],
|
|
545
|
+
[/\bFurthermore\b/g, 'Also'],
|
|
546
|
+
[/\bserves as\b/gi, 'is'],
|
|
547
|
+
[/\bstands as\b/gi, 'is'],
|
|
548
|
+
[/\brepresents a\b/gi, 'is a'],
|
|
549
|
+
[/\bdelve into\b/gi, 'look at'],
|
|
550
|
+
[/\bdelve\b/gi, 'explore'],
|
|
551
|
+
[/\bnavigate\b/gi, 'use'],
|
|
552
|
+
[/\bleverage\b/gi, 'use'],
|
|
553
|
+
[/\butilize\b/gi, 'use'],
|
|
554
|
+
[/\bseamless\b/gi, 'smooth'],
|
|
555
|
+
[/\brobust\b/gi, 'strong'],
|
|
556
|
+
[/\bpivotal\b/gi, 'important'],
|
|
557
|
+
[/\bcrucial\b/gi, 'important'],
|
|
558
|
+
[/\ba testament to\b/gi, 'shows'],
|
|
559
|
+
[/\bunderscore\b/gi, 'show'],
|
|
560
|
+
[/\bhighlight\b/gi, 'show'],
|
|
561
|
+
[/\bensuring\b/gi, 'so'],
|
|
562
|
+
[/\bfostering\b/gi, 'building'],
|
|
563
|
+
[/\benhancing\b/gi, 'improving'],
|
|
564
|
+
];
|
|
565
|
+
for (const [pattern, replacement] of vocabularyReplacements) {
|
|
566
|
+
result = result.replace(pattern, replacement);
|
|
567
|
+
}
|
|
568
|
+
// Remove filler phrases
|
|
569
|
+
const fillerPatterns = [
|
|
570
|
+
[/In order to\b/gi, 'To'],
|
|
571
|
+
[/Due to the fact that\b/gi, 'Because'],
|
|
572
|
+
[/At this point in time\b/gi, 'Now'],
|
|
573
|
+
[/In the event that\b/gi, 'If'],
|
|
574
|
+
[/It is important to note that\b/gi, ''],
|
|
575
|
+
[/It should be noted that\b/gi, ''],
|
|
576
|
+
[/As you may know,?\s*/gi, ''],
|
|
577
|
+
[/As mentioned earlier,?\s*/gi, ''],
|
|
578
|
+
];
|
|
579
|
+
for (const [pattern, replacement] of fillerPatterns) {
|
|
580
|
+
result = result.replace(pattern, replacement);
|
|
581
|
+
}
|
|
582
|
+
// Remove excessive em dashes (replace with commas or periods)
|
|
583
|
+
// Keep at most one em dash per paragraph
|
|
584
|
+
const paragraphs = result.split('\n\n');
|
|
585
|
+
result = paragraphs.map(para => {
|
|
586
|
+
const emDashCount = (para.match(/—/g) || []).length;
|
|
587
|
+
if (emDashCount > 1) {
|
|
588
|
+
// Replace all but the first em dash with commas
|
|
589
|
+
let count = 0;
|
|
590
|
+
return para.replace(/—/g, () => {
|
|
591
|
+
count++;
|
|
592
|
+
return count === 1 ? '—' : ',';
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
return para;
|
|
596
|
+
}).join('\n\n');
|
|
597
|
+
// Strip Markdown formatting (for plain text emails)
|
|
598
|
+
// Remove bold: **text** or __text__
|
|
599
|
+
result = result.replace(/\*\*([^*]+)\*\*/g, '$1');
|
|
600
|
+
result = result.replace(/__([^_]+)__/g, '$1');
|
|
601
|
+
// Remove italics: *text* or _text_ (but not bullet points)
|
|
602
|
+
result = result.replace(/(?<!\n)\*([^*\n]+)\*(?!\*)/g, '$1');
|
|
603
|
+
// Remove headers: ## Header or ### Header
|
|
604
|
+
result = result.replace(/^#{1,6}\s+/gm, '');
|
|
605
|
+
// Fix double spaces that may result from removals
|
|
606
|
+
result = result.replace(/ +/g, ' ');
|
|
607
|
+
// Fix sentence starts after removals (capitalize)
|
|
608
|
+
result = result.replace(/\.\s+([a-z])/g, (_, letter) => `. ${letter.toUpperCase()}`);
|
|
609
|
+
// Trim whitespace
|
|
610
|
+
result = result.trim();
|
|
611
|
+
return result;
|
|
612
|
+
}
|
|
613
|
+
// =============================================================================
|
|
614
|
+
// Singleton and Utility Functions
|
|
615
|
+
// =============================================================================
|
|
616
|
+
let generationService = null;
|
|
617
|
+
export function getResponseGenerationService(configOverride) {
|
|
618
|
+
// If configOverride is provided, always create a new instance with that config
|
|
619
|
+
if (configOverride) {
|
|
620
|
+
return new ResponseGenerationService(configOverride);
|
|
621
|
+
}
|
|
622
|
+
// Otherwise, use the singleton pattern with global config
|
|
623
|
+
if (!generationService) {
|
|
624
|
+
generationService = new ResponseGenerationService();
|
|
625
|
+
}
|
|
626
|
+
return generationService;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Generate a response for a message
|
|
630
|
+
*/
|
|
631
|
+
export async function generateResponse(message, analysis, knowledge, options) {
|
|
632
|
+
return getResponseGenerationService().generateResponse(message, analysis, knowledge, options);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Check if response is ready to send
|
|
636
|
+
*/
|
|
637
|
+
export function isResponseReadyToSend(response) {
|
|
638
|
+
return (response.brandCompliance.status === 'compliant' &&
|
|
639
|
+
response.qualityScore >= 0.7);
|
|
640
|
+
}
|
|
641
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generation/index.ts"],"names":[],"mappings":"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"}
|