import { z } from 'zod';
import { createLogger } from '../utils/logger.js';
import { responseAdapter } from './response-adapter.js';
/**
* Conversational Bridge Service
*
* Transforms structured responses into natural, conversational language
* that feels like talking to a knowledgeable advisor rather than a system.
*/
// Conversation schemas
export const ConversationStyleSchema = z.enum([
'professional',
'friendly',
'executive',
'technical',
'educational'
]);
export const ConversationalResponseSchema = z.object({
message: z.string(),
tone: z.object({
style: ConversationStyleSchema,
formality: z.number().min(0).max(1),
enthusiasm: z.number().min(0).max(1),
confidence: z.number().min(0).max(1)
}),
elements: z.object({
greeting: z.string().optional(),
context_acknowledgment: z.string().optional(),
main_content: z.array(z.string()),
clarifications: z.array(z.string()).optional(),
closing: z.string().optional()
}),
interactive: z.object({
follow_up_questions: z.array(z.string()).optional(),
suggested_topics: z.array(z.string()).optional(),
clarification_prompts: z.array(z.string()).optional()
}),
metadata: z.object({
word_count: z.number(),
reading_time_seconds: z.number(),
complexity_level: z.enum(['simple', 'moderate', 'complex']),
jargon_count: z.number()
})
});
export type ConversationStyle = z.infer<typeof ConversationStyleSchema>;
export type ConversationalResponse = z.infer<typeof ConversationalResponseSchema>;
export class ConversationalBridge {
private logger = createLogger({ component: 'ConversationalBridge' });
// Conversation templates
private readonly CONVERSATION_TEMPLATES = {
greetings: {
professional: ['Let me analyze this for you.', 'I\'ve reviewed the data.', 'Here\'s what I found.'],
friendly: ['Great question! Let me break this down.', 'I\'d be happy to help with that!', 'Let\'s explore this together.'],
executive: ['Executive summary:', 'Key findings:', 'Bottom line:'],
technical: ['Technical analysis indicates:', 'Based on the data:', 'System analysis shows:'],
educational: ['Let me explain what this means.', 'Here\'s a helpful way to think about it.', 'To understand this better:']
},
transitions: {
to_positive: ['On the bright side,', 'The good news is', 'Encouragingly,'],
to_negative: ['However,', 'That said,', 'One consideration is'],
to_detail: ['Diving deeper,', 'Looking more closely,', 'Specifically,'],
to_summary: ['In summary,', 'The key takeaway is', 'Overall,']
},
closings: {
professional: ['Would you like more details on any aspect?', 'Please let me know if you need clarification.'],
friendly: ['Hope this helps! Any other questions?', 'Feel free to ask if you\'d like to explore further!'],
executive: ['Ready to proceed with implementation?', 'Shall we discuss next steps?'],
technical: ['Additional technical details available upon request.', 'Further analysis can be provided.'],
educational: ['Does this make sense? Happy to explain differently!', 'Would you like me to elaborate on any part?']
}
};
/**
* Transform response into conversational format
*/
async transformToConversation(
response: any,
style: ConversationStyle = 'professional',
context?: {
user_expertise?: 'beginner' | 'intermediate' | 'expert';
previous_interactions?: number;
urgency?: 'low' | 'medium' | 'high';
}
): Promise<ConversationalResponse> {
this.logger.debug('Transforming to conversational format', { style, context });
// Determine tone based on style and context
const tone = this.determineTone(style, context);
// Build conversation elements
const elements = await this.buildConversationElements(response, style, tone, context);
// Generate interactive elements
const interactive = this.generateInteractiveElements(response, context);
// Compose final message
const message = this.composeMessage(elements, tone);
// Calculate metadata
const metadata = this.calculateMetadata(message, elements);
return {
message,
tone,
elements,
interactive,
metadata
};
}
/**
* Generate natural language explanations
*/
async explainInNaturalLanguage(
concept: string,
data: any,
targetAudience: 'executive' | 'technical' | 'general' = 'general'
): Promise<string> {
this.logger.debug('Generating natural language explanation', { concept, targetAudience });
switch (concept) {
case 'roi':
return this.explainROI(data, targetAudience);
case 'payback_period':
return this.explainPaybackPeriod(data, targetAudience);
case 'risk_factors':
return this.explainRiskFactors(data, targetAudience);
case 'implementation_timeline':
return this.explainTimeline(data, targetAudience);
case 'cost_breakdown':
return this.explainCosts(data, targetAudience);
default:
return this.explainGeneric(concept, data, targetAudience);
}
}
/**
* Create conversational narratives from data
*/
async createNarrative(
data: any,
narrativeType: 'success_story' | 'cautionary_tale' | 'comparison' | 'journey'
): Promise<{
narrative: string;
key_points: string[];
emotional_arc: string[];
}> {
this.logger.debug('Creating narrative', { narrativeType });
switch (narrativeType) {
case 'success_story':
return this.createSuccessStory(data);
case 'cautionary_tale':
return this.createCautionaryTale(data);
case 'comparison':
return this.createComparisonNarrative(data);
case 'journey':
return this.createJourneyNarrative(data);
default:
return this.createGenericNarrative(data);
}
}
/**
* Handle conversational context and memory
*/
async maintainConversationFlow(
currentResponse: any,
conversationHistory: Array<{
role: 'user' | 'assistant';
content: string;
timestamp: string;
}>
): Promise<{
contextual_response: string;
references_to_past: string[];
conversation_continuity: number;
}> {
this.logger.debug('Maintaining conversation flow', {
history_length: conversationHistory.length
});
// Analyze conversation history
const context = this.analyzeConversationContext(conversationHistory);
// Build contextual response
const contextualResponse = this.buildContextualResponse(
currentResponse,
context,
conversationHistory
);
// Find references to past interactions
const references = this.findPastReferences(currentResponse, conversationHistory);
// Calculate conversation continuity score
const continuity = this.calculateContinuity(conversationHistory, contextualResponse);
return {
contextual_response: contextualResponse,
references_to_past: references,
conversation_continuity: continuity
};
}
/**
* Adapt language complexity based on audience
*/
async adaptComplexity(
content: string,
targetComplexity: 'simple' | 'moderate' | 'complex',
preserveAccuracy: boolean = true
): Promise<{
adapted_content: string;
complexity_changes: string[];
accuracy_preserved: boolean;
}> {
this.logger.debug('Adapting language complexity', { targetComplexity });
let adaptedContent = content;
const changes: string[] = [];
if (targetComplexity === 'simple') {
// Simplify jargon
adaptedContent = this.simplifyJargon(adaptedContent);
changes.push('Replaced technical terms with simpler language');
// Shorten sentences
adaptedContent = this.shortenSentences(adaptedContent);
changes.push('Broke down complex sentences');
// Add analogies
adaptedContent = this.addSimpleAnalogies(adaptedContent);
changes.push('Added relatable analogies');
} else if (targetComplexity === 'complex') {
// Add technical details
adaptedContent = this.addTechnicalDetails(adaptedContent);
changes.push('Enhanced with technical specifications');
// Include precise terminology
adaptedContent = this.usePreciseTerminology(adaptedContent);
changes.push('Used industry-specific terminology');
}
// Verify accuracy wasn't compromised
const accuracyPreserved = preserveAccuracy ?
this.verifyAccuracy(content, adaptedContent) : true;
return {
adapted_content: adaptedContent,
complexity_changes: changes,
accuracy_preserved: accuracyPreserved
};
}
// Private helper methods
private determineTone(
style: ConversationStyle,
context?: any
): ConversationalResponse['tone'] {
const toneMap = {
professional: { formality: 0.8, enthusiasm: 0.4, confidence: 0.8 },
friendly: { formality: 0.4, enthusiasm: 0.8, confidence: 0.7 },
executive: { formality: 0.9, enthusiasm: 0.3, confidence: 0.9 },
technical: { formality: 0.7, enthusiasm: 0.5, confidence: 0.8 },
educational: { formality: 0.5, enthusiasm: 0.7, confidence: 0.7 }
};
const baseTone = toneMap[style];
// Adjust based on context
if (context?.urgency === 'high') {
baseTone.formality += 0.1;
baseTone.enthusiasm -= 0.1;
}
if (context?.user_expertise === 'beginner') {
baseTone.formality -= 0.1;
baseTone.enthusiasm += 0.1;
}
return {
style,
formality: Math.max(0, Math.min(1, baseTone.formality)),
enthusiasm: Math.max(0, Math.min(1, baseTone.enthusiasm)),
confidence: Math.max(0, Math.min(1, baseTone.confidence))
};
}
private async buildConversationElements(
response: any,
style: ConversationStyle,
tone: any,
context?: any
): Promise<ConversationalResponse['elements']> {
const elements: ConversationalResponse['elements'] = {
main_content: []
};
// Add greeting if appropriate
if (!context?.previous_interactions || context.previous_interactions < 2) {
elements.greeting = this.selectGreeting(style, tone);
}
// Acknowledge context if relevant
if (context?.urgency === 'high') {
elements.context_acknowledgment = "I understand this is time-sensitive.";
}
// Build main content
elements.main_content = this.buildMainContent(response, style);
// Add clarifications if needed
if (this.needsClarification(response)) {
elements.clarifications = this.generateClarifications(response);
}
// Add closing
elements.closing = this.selectClosing(style, context);
return elements;
}
private generateInteractiveElements(
response: any,
context?: any
): ConversationalResponse['interactive'] {
const interactive: ConversationalResponse['interactive'] = {};
// Generate follow-up questions
interactive.follow_up_questions = this.generateFollowUpQuestions(response);
// Suggest related topics
interactive.suggested_topics = this.suggestRelatedTopics(response);
// Add clarification prompts if complexity is high
if (this.isComplex(response)) {
interactive.clarification_prompts = [
"Would you like me to explain any of these terms?",
"Should I break down the calculations?",
"Need more context on the assumptions?"
];
}
return interactive;
}
private composeMessage(
elements: ConversationalResponse['elements'],
tone: any
): string {
let message = '';
if (elements.greeting) {
message += elements.greeting + ' ';
}
if (elements.context_acknowledgment) {
message += elements.context_acknowledgment + ' ';
}
message += elements.main_content.join(' ');
if (elements.clarifications && elements.clarifications.length > 0) {
message += '\n\n' + elements.clarifications.join(' ');
}
if (elements.closing) {
message += '\n\n' + elements.closing;
}
return message.trim();
}
private calculateMetadata(
message: string,
elements: any
): ConversationalResponse['metadata'] {
const words = message.split(/\s+/).length;
const readingTime = Math.ceil(words / 200); // 200 words per minute
const jargonTerms = this.countJargon(message);
const complexity = this.assessComplexity(message);
return {
word_count: words,
reading_time_seconds: readingTime * 60,
complexity_level: complexity,
jargon_count: jargonTerms
};
}
private selectGreeting(style: ConversationStyle, tone: any): string {
const greetings = this.CONVERSATION_TEMPLATES.greetings[style];
return greetings[Math.floor(Math.random() * greetings.length)];
}
private selectClosing(style: ConversationStyle, context?: any): string {
const closings = this.CONVERSATION_TEMPLATES.closings[style];
return closings[Math.floor(Math.random() * closings.length)];
}
private buildMainContent(response: any, style: ConversationStyle): string[] {
const content: string[] = [];
// Start with the key finding
if (response.executive_summary?.key_insight) {
content.push(this.phraseKeyInsight(response.executive_summary.key_insight, style));
}
// Add supporting details with transitions
if (response.insights?.primary) {
const transition = this.CONVERSATION_TEMPLATES.transitions.to_detail[0];
content.push(`${transition} ${response.insights.primary[0]}`);
}
// Include risks with appropriate framing
if (response.insights?.risks && response.insights.risks.length > 0) {
const transition = this.CONVERSATION_TEMPLATES.transitions.to_negative[0];
content.push(`${transition} ${this.phraseRisk(response.insights.risks[0], style)}`);
}
// End with recommendation
if (response.recommendations?.next_action) {
const transition = this.CONVERSATION_TEMPLATES.transitions.to_summary[0];
content.push(`${transition} I recommend ${response.recommendations.next_action.toLowerCase()}.`);
}
return content;
}
private phraseKeyInsight(insight: string, style: ConversationStyle): string {
switch (style) {
case 'executive':
return `The critical insight: ${insight}`;
case 'friendly':
return `Here's what stands out: ${insight}`;
case 'technical':
return `Analysis reveals: ${insight}`;
case 'educational':
return `The main learning here is that ${insight}`;
default:
return insight;
}
}
private phraseRisk(risk: string, style: ConversationStyle): string {
switch (style) {
case 'executive':
return `a key risk to manage is ${risk}`;
case 'friendly':
return `something to keep an eye on is ${risk}`;
case 'technical':
return `risk analysis indicates ${risk}`;
default:
return `there's a risk of ${risk}`;
}
}
private needsClarification(response: any): boolean {
// Check if response contains complex terms or calculations
return response.metadata?.confidence_score < 0.8 ||
response.insights?.risks?.length > 3 ||
response.summary?.payback_period_months > 24;
}
private generateClarifications(response: any): string[] {
const clarifications: string[] = [];
if (response.metadata?.confidence_score < 0.8) {
clarifications.push(
"Note that confidence is moderate due to some assumptions in the data."
);
}
if (response.summary?.payback_period_months > 24) {
clarifications.push(
"The extended payback period reflects the scale of investment required."
);
}
return clarifications;
}
private generateFollowUpQuestions(response: any): string[] {
const questions: string[] = [];
if (response.insights?.opportunities?.length > 0) {
questions.push("Would you like to explore the growth opportunities in more detail?");
}
if (response.insights?.risks?.length > 0) {
questions.push("Should we discuss risk mitigation strategies?");
}
if (response.recommendations?.alternatives?.length > 0) {
questions.push("Want to compare alternative approaches?");
}
return questions;
}
private suggestRelatedTopics(response: any): string[] {
const topics: string[] = [];
if (response.summary?.expected_roi > 100) {
topics.push("Implementation roadmap planning");
topics.push("Quick wins identification");
}
if (response.insights?.patterns?.length > 0) {
topics.push("Industry benchmark comparison");
topics.push("Best practices from similar projects");
}
return topics;
}
private isComplex(response: any): boolean {
return response.use_cases?.length > 5 ||
response.financial_metrics?.scenarios?.length > 3 ||
(response.metadata?.assumptions?.length || 0) > 5;
}
private countJargon(text: string): number {
const jargonTerms = [
'ROI', 'NPV', 'IRR', 'payback period', 'automation', 'scalability',
'implementation', 'optimization', 'integration', 'deployment'
];
let count = 0;
jargonTerms.forEach(term => {
const regex = new RegExp(term, 'gi');
const matches = text.match(regex);
count += matches ? matches.length : 0;
});
return count;
}
private assessComplexity(text: string): 'simple' | 'moderate' | 'complex' {
const avgSentenceLength = text.split(/[.!?]/).filter(s => s.trim()).map(s =>
s.split(/\s+/).length
).reduce((a, b) => a + b, 0) / (text.split(/[.!?]/).length || 1);
const jargonDensity = this.countJargon(text) / (text.split(/\s+/).length || 1);
if (avgSentenceLength < 15 && jargonDensity < 0.05) return 'simple';
if (avgSentenceLength > 25 || jargonDensity > 0.1) return 'complex';
return 'moderate';
}
// Natural language explanation methods
private explainROI(data: any, audience: string): string {
const roi = data.summary?.expected_roi || data;
switch (audience) {
case 'executive':
return `This investment is projected to return ${roi}% over 5 years, meaning every dollar invested will generate $${(roi/100).toFixed(2)} in value.`;
case 'technical':
return `ROI calculation: ((Total Benefits - Total Costs) / Total Costs) × 100 = ${roi}%. This includes discounted cash flows at ${data.discount_rate || 10}% annual rate.`;
case 'general':
return `Think of ROI like this: if you invest $100, you'll get back $${100 + roi} total. That's a ${roi}% return on your investment.`;
default:
return `ROI: ${roi}%`;
}
}
private explainPaybackPeriod(data: any, audience: string): string {
const months = data.summary?.payback_period_months || data;
const years = Math.floor(months / 12);
const remainingMonths = months % 12;
const timeStr = years > 0 ?
`${years} year${years > 1 ? 's' : ''}${remainingMonths > 0 ? ` and ${remainingMonths} month${remainingMonths > 1 ? 's' : ''}` : ''}` :
`${months} month${months > 1 ? 's' : ''}`;
switch (audience) {
case 'executive':
return `You'll recoup your investment in ${timeStr}, after which all benefits are pure profit.`;
case 'technical':
return `Payback achieved when cumulative discounted cash flows equal initial investment: ${timeStr} based on projected monthly benefits.`;
case 'general':
return `It will take ${timeStr} to earn back what you invested. After that, it's all profit!`;
default:
return `Payback period: ${timeStr}`;
}
}
private explainRiskFactors(data: any, audience: string): string {
const risks = data.insights?.risks || data;
const topRisk = Array.isArray(risks) ? risks[0] : risks;
switch (audience) {
case 'executive':
return `Primary risk exposure: ${topRisk}. Mitigation strategies are available and should be implemented proactively.`;
case 'technical':
return `Risk assessment identifies ${topRisk} with potential impact on timeline and budget. Recommend implementing controls.`;
case 'general':
return `The main thing to watch out for is ${topRisk}. We can plan ahead to handle this.`;
default:
return `Key risk: ${topRisk}`;
}
}
private explainTimeline(data: any, audience: string): string {
const months = data.timeline_months || data;
switch (audience) {
case 'executive':
return `Full implementation requires ${months} months, with value realization beginning in month ${Math.ceil(months * 0.3)}.`;
case 'technical':
return `Project timeline: ${months} months including ${Math.ceil(months * 0.25)} months planning, ${Math.ceil(months * 0.5)} months implementation, ${Math.ceil(months * 0.25)} months optimization.`;
case 'general':
return `The project will take about ${months} months from start to finish. You'll start seeing benefits about ${Math.ceil(months * 0.3)} months in.`;
default:
return `Timeline: ${months} months`;
}
}
private explainCosts(data: any, audience: string): string {
const cost = data.summary?.total_investment || data;
const costK = Math.round(cost / 1000);
switch (audience) {
case 'executive':
return `Total investment requirement: $${costK}K, with ${data.breakdown?.development || 60}% for development and ${data.breakdown?.infrastructure || 40}% for infrastructure.`;
case 'technical':
return `Cost breakdown: $${costK}K total, comprising development hours, infrastructure, licensing, and ongoing operational expenses.`;
case 'general':
return `You'll need to invest about $${costK}K total. This covers everything from building the solution to keeping it running.`;
default:
return `Total cost: $${costK}K`;
}
}
private explainGeneric(concept: string, data: any, audience: string): string {
return `${concept}: ${JSON.stringify(data)}`;
}
// Narrative creation methods
private createSuccessStory(data: any): any {
const roi = data.summary?.expected_roi || 0;
const payback = data.summary?.payback_period_months || 0;
const narrative = `This is a story of transformation. Starting with an investment of $${Math.round((data.summary?.total_investment || 0) / 1000)}K, ` +
`the organization embarked on a journey that would yield ${roi}% returns. ` +
`Within just ${payback} months, the investment paid for itself. ` +
`The key was focusing on ${data.insights?.primary?.[0] || 'strategic automation'}. ` +
`Today, the benefits continue to compound, validating the initial vision.`;
return {
narrative,
key_points: [
`${roi}% ROI achieved`,
`${payback} month payback period`,
'Successful transformation'
],
emotional_arc: ['challenge', 'decision', 'implementation', 'success', 'growth']
};
}
private createCautionaryTale(data: any): any {
const risks = data.insights?.risks || [];
const narrative = `While the opportunity showed promise, several risks demanded attention. ` +
`${risks[0] || 'Implementation complexity'} posed the greatest challenge. ` +
`Without proper mitigation, what started as a ${data.summary?.expected_roi || 0}% ROI opportunity ` +
`could easily turn into a costly lesson. The key learning: thorough preparation and risk management ` +
`are not optional—they're essential for success.`;
return {
narrative,
key_points: risks.slice(0, 3),
emotional_arc: ['optimism', 'discovery', 'concern', 'caution', 'wisdom']
};
}
private createComparisonNarrative(data: any): any {
const narrative = `When comparing options, the differences become clear. ` +
`Option A offers ${data.option_a?.roi || 0}% ROI with a ${data.option_a?.payback || 0}-month payback. ` +
`Option B provides ${data.option_b?.roi || 0}% ROI but takes ${data.option_b?.payback || 0} months to pay back. ` +
`The choice depends on your priorities: immediate returns or long-term value.`;
return {
narrative,
key_points: ['Clear tradeoffs', 'Different timelines', 'Strategic choice required'],
emotional_arc: ['analysis', 'comparison', 'insight', 'decision']
};
}
private createJourneyNarrative(data: any): any {
const narrative = `Every transformation begins with a single step. ` +
`Month 1-3: Foundation building and planning. ` +
`Month 4-9: Implementation and initial results. ` +
`Month 10-${data.timeline_months || 12}: Optimization and scaling. ` +
`By month ${data.summary?.payback_period_months || 18}, the journey reaches a milestone: full payback. ` +
`But this isn't the end—it's just the beginning of sustained value creation.`;
return {
narrative,
key_points: ['Phased approach', 'Clear milestones', 'Long-term value'],
emotional_arc: ['beginning', 'progress', 'challenges', 'breakthrough', 'momentum', 'success']
};
}
private createGenericNarrative(data: any): any {
return {
narrative: `This analysis reveals key insights about the opportunity at hand.`,
key_points: ['Data-driven insights', 'Clear recommendations', 'Actionable next steps'],
emotional_arc: ['discovery', 'analysis', 'conclusion']
};
}
// Conversation flow methods
private analyzeConversationContext(history: any[]): any {
const topics = new Set<string>();
const sentiment = { positive: 0, negative: 0, neutral: 0 };
let lastTopic = '';
history.forEach(entry => {
// Extract topics (simplified)
if (entry.content.toLowerCase().includes('roi')) topics.add('roi');
if (entry.content.toLowerCase().includes('risk')) topics.add('risk');
if (entry.content.toLowerCase().includes('timeline')) topics.add('timeline');
// Track sentiment (simplified)
if (entry.content.includes('great') || entry.content.includes('excellent')) {
sentiment.positive++;
} else if (entry.content.includes('concern') || entry.content.includes('worry')) {
sentiment.negative++;
} else {
sentiment.neutral++;
}
});
if (history.length > 0) {
const lastEntry = history[history.length - 1].content.toLowerCase();
if (lastEntry.includes('roi')) lastTopic = 'roi';
else if (lastEntry.includes('risk')) lastTopic = 'risk';
else if (lastEntry.includes('timeline')) lastTopic = 'timeline';
}
return { topics: Array.from(topics), sentiment, lastTopic };
}
private buildContextualResponse(
currentResponse: any,
context: any,
history: any[]
): string {
let response = '';
// Reference previous topics if relevant
if (context.topics.includes('roi') && currentResponse.summary?.expected_roi) {
response += `As we discussed earlier about ROI, `;
}
// Acknowledge sentiment
if (context.sentiment.negative > context.sentiment.positive) {
response += `I understand your concerns. Let me address them: `;
}
// Build on last topic
if (context.lastTopic && currentResponse[context.lastTopic]) {
response += `Building on our ${context.lastTopic} discussion, `;
}
// Add current response content
response += this.buildMainContent(currentResponse, 'professional').join(' ');
return response;
}
private findPastReferences(current: any, history: any[]): string[] {
const references: string[] = [];
history.forEach((entry, idx) => {
// Look for related content
if (entry.content.includes('roi') && current.summary?.expected_roi) {
references.push(`Relates to ROI discussion from earlier`);
}
if (entry.content.includes('timeline') && current.timeline_months) {
references.push(`Connects to timeline mentioned previously`);
}
});
return Array.from(new Set(references));
}
private calculateContinuity(history: any[], response: string): number {
if (history.length === 0) return 1.0;
// Simple continuity score based on topic overlap
const lastEntry = history[history.length - 1].content.toLowerCase();
const responseWords = response.toLowerCase().split(/\s+/);
const lastWords = lastEntry.split(/\s+/);
const overlap = responseWords.filter(word =>
lastWords.includes(word) && word.length > 3
).length;
return Math.min(1, overlap / 10);
}
// Complexity adaptation methods
private simplifyJargon(text: string): string {
const jargonMap = {
'ROI': 'return on investment',
'NPV': 'net present value',
'payback period': 'time to earn back investment',
'implementation': 'setup and installation',
'scalability': 'ability to grow',
'automation': 'automatic processing'
};
let simplified = text;
Object.entries(jargonMap).forEach(([jargon, simple]) => {
simplified = simplified.replace(new RegExp(jargon, 'gi'), simple);
});
return simplified;
}
private shortenSentences(text: string): string {
const sentences = text.split(/(?<=[.!?])\s+/);
return sentences.map(sentence => {
const words = sentence.split(/\s+/);
if (words.length > 20) {
// Break into smaller sentences
const mid = Math.floor(words.length / 2);
return words.slice(0, mid).join(' ') + '. ' +
words.slice(mid).join(' ');
}
return sentence;
}).join(' ');
}
private addSimpleAnalogies(text: string): string {
if (text.includes('return on investment')) {
text += ' (like earning interest on savings)';
}
if (text.includes('payback')) {
text += ' (like paying off a loan)';
}
return text;
}
private addTechnicalDetails(text: string): string {
if (text.includes('ROI')) {
text = text.replace('ROI', 'ROI (calculated using DCF methodology)');
}
if (text.includes('implementation')) {
text = text.replace('implementation', 'implementation (including CI/CD pipeline setup)');
}
return text;
}
private usePreciseTerminology(text: string): string {
const preciseTerms = {
'setup': 'implementation and deployment',
'money saved': 'cost reduction',
'making money': 'revenue generation',
'getting better': 'optimization'
};
let precise = text;
Object.entries(preciseTerms).forEach(([simple, technical]) => {
precise = precise.replace(new RegExp(simple, 'gi'), technical as string);
});
return precise;
}
private verifyAccuracy(original: string, adapted: string): boolean {
// Check that key numbers haven't changed
const originalNumbers: string[] = original.match(/\d+/g) || [];
const adaptedNumbers: string[] = adapted.match(/\d+/g) || [];
return originalNumbers.every(num => adaptedNumbers.includes(num));
}
}
// Export singleton instance
export const conversationalBridge = new ConversationalBridge();