Skip to main content
Glama
response-generator.ts14 kB
/** * Natural Language Response Generator * Generates natural language responses for user commands */ import { Intent, RecognizedIntent, NLResponse } from '../types/nl.js'; import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { CommandExecutionResult } from './command-handlers.js'; import logger from '../../../logger.js'; /** * Response generation context */ export interface ResponseContext { sessionId: string; userId?: string; userPreferences: Record<string, unknown>; conversationHistory: RecognizedIntent[]; currentProject?: string; currentTask?: string; } /** * Response generation configuration */ export interface ResponseGeneratorConfig { /** Whether to include suggestions in responses */ includeSuggestions: boolean; /** Maximum number of suggestions to include */ maxSuggestions: number; /** Whether to personalize responses */ enablePersonalization: boolean; /** Response tone (formal, casual, technical) */ tone: 'formal' | 'casual' | 'technical'; /** Whether to include emojis in responses */ includeEmojis: boolean; } /** * Natural Language Response Generator * Converts command execution results into natural language responses */ export class ResponseGenerator { private static instance: ResponseGenerator; private config: ResponseGeneratorConfig; private constructor() { this.config = { includeSuggestions: true, maxSuggestions: 3, enablePersonalization: true, tone: 'casual', includeEmojis: true }; } /** * Get singleton instance */ static getInstance(): ResponseGenerator { if (!ResponseGenerator.instance) { ResponseGenerator.instance = new ResponseGenerator(); } return ResponseGenerator.instance; } /** * Generate natural language response from command execution result */ generateResponse( executionResult: CommandExecutionResult, recognizedIntent: RecognizedIntent, context: ResponseContext ): NLResponse { try { logger.debug({ intent: recognizedIntent.intent, success: executionResult.success, sessionId: context.sessionId }, 'Generating natural language response'); if (executionResult.success) { return this.generateSuccessResponse(executionResult, recognizedIntent, context); } else { return this.generateErrorResponse(executionResult, recognizedIntent, context); } } catch (error) { logger.error({ err: error, sessionId: context.sessionId }, 'Response generation failed'); return { text: 'I encountered an error while processing your request. Please try again.', type: 'error', requiresConfirmation: false, suggestions: ['Try rephrasing your request', 'Check the command syntax'], metadata: { generatedAt: new Date(), method: 'template', confidence: 0 } }; } } /** * Generate success response */ private generateSuccessResponse( executionResult: CommandExecutionResult, recognizedIntent: RecognizedIntent, context: ResponseContext ): NLResponse { const baseText = this.extractTextFromResult(executionResult.result); const personalizedText = this.personalizeResponse(baseText, recognizedIntent, context); const suggestions = this.generateSuggestions(executionResult, recognizedIntent, context); return { text: personalizedText, type: 'success', data: { intent: recognizedIntent.intent, confidence: recognizedIntent.confidence, updatedContext: executionResult.updatedContext }, suggestions, requiresConfirmation: false, metadata: { generatedAt: new Date(), method: 'template', confidence: recognizedIntent.confidence } }; } /** * Generate error response */ private generateErrorResponse( executionResult: CommandExecutionResult, recognizedIntent: RecognizedIntent, context: ResponseContext ): NLResponse { const baseText = this.extractTextFromResult(executionResult.result); const helpfulText = this.makeErrorHelpful(baseText, recognizedIntent, context); const suggestions = this.generateErrorSuggestions(executionResult, recognizedIntent, context); return { text: helpfulText, type: 'error', data: { intent: recognizedIntent.intent, confidence: recognizedIntent.confidence }, suggestions, requiresConfirmation: false, metadata: { generatedAt: new Date(), method: 'template', confidence: recognizedIntent.confidence } }; } /** * Extract text content from CallToolResult */ private extractTextFromResult(result: CallToolResult): string { if (result.content && result.content.length > 0) { const textContent = result.content.find(c => c.type === 'text'); return textContent ? textContent.text : 'Command completed successfully.'; } return 'Command completed successfully.'; } /** * Personalize response based on context and preferences */ private personalizeResponse( text: string, recognizedIntent: RecognizedIntent, context: ResponseContext ): string { if (!this.config.enablePersonalization) { return text; } let personalizedText = text; // Add context-aware greetings for first interaction if (context.conversationHistory.length === 0) { const greeting = this.getContextualGreeting(recognizedIntent.intent); if (greeting) { personalizedText = `${greeting}\n\n${personalizedText}`; } } // Add project context if relevant if (context.currentProject && !text.includes(context.currentProject)) { const projectContext = this.getProjectContext(recognizedIntent.intent, context.currentProject); if (projectContext) { personalizedText += `\n\n${projectContext}`; } } // Adjust tone based on configuration personalizedText = this.adjustTone(personalizedText, this.config.tone); return personalizedText; } /** * Get contextual greeting for first interaction */ private getContextualGreeting(intent: Intent): string | null { const greetings: Partial<Record<Intent, string>> = { 'create_project': '🚀 Great! Let\'s get your new project started.', 'create_task': '📝 Perfect! I\'ll help you create that task.', 'list_projects': '📋 Here\'s an overview of your projects.', 'list_tasks': '📝 Let me show you your tasks.', 'run_task': '⚡ Time to get some work done!', 'check_status': '📊 Let me check on that for you.', 'decompose_task': '🔍 I\'ll break that down into manageable pieces.', 'decompose_epic': '📋 I\'ll decompose that epic into actionable tasks.', 'refine_task': '✨ Let\'s refine that task to make it clearer.', 'assign_task': '👥 I\'ll help you assign that task.', 'get_help': '💡 I\'m here to help!', 'open_project': '📂 Opening that project for you.' }; return greetings[intent] || null; } /** * Get project context information */ private getProjectContext(intent: Intent, currentProject: string): string | null { const contextMessages: Partial<Record<Intent, string>> = { 'create_task': `This task will be added to your current project: ${currentProject}.`, 'list_tasks': `Showing tasks for your current project: ${currentProject}.`, 'check_status': `Current project context: ${currentProject}.`, 'run_task': `Executing within project: ${currentProject}.` }; return contextMessages[intent] || null; } /** * Adjust response tone */ private adjustTone(text: string, tone: 'formal' | 'casual' | 'technical'): string { switch (tone) { case 'formal': return text .replace(/Great!/g, 'Excellent.') .replace(/Perfect!/g, 'Very good.') .replace(/Let's/g, 'We shall') .replace(/I'll/g, 'I will'); case 'technical': return text .replace(/Great!/g, 'Operation successful.') .replace(/Perfect!/g, 'Command executed.') .replace(/Let me/g, 'Processing'); case 'casual': default: return text; // Keep casual tone as default } } /** * Generate suggestions for successful commands */ private generateSuggestions( executionResult: CommandExecutionResult, recognizedIntent: RecognizedIntent, context: ResponseContext ): string[] { const suggestions: string[] = []; // Use follow-up suggestions from execution result if available if (executionResult.followUpSuggestions) { suggestions.push(...executionResult.followUpSuggestions.slice(0, this.config.maxSuggestions)); } // Add intent-specific suggestions if we have room if (suggestions.length < this.config.maxSuggestions) { const intentSuggestions = this.getIntentSpecificSuggestions(recognizedIntent.intent, context); const remainingSlots = this.config.maxSuggestions - suggestions.length; suggestions.push(...intentSuggestions.slice(0, remainingSlots)); } return suggestions; } /** * Generate suggestions for error responses */ private generateErrorSuggestions( executionResult: CommandExecutionResult, recognizedIntent: RecognizedIntent, _context: ResponseContext ): string[] { const suggestions = [ 'Try rephrasing your request', 'Check the command syntax', 'Ask for help with available commands' ]; // Add intent-specific error suggestions const intentSuggestions = this.getErrorSuggestionsForIntent(recognizedIntent.intent); suggestions.push(...intentSuggestions); return suggestions.slice(0, this.config.maxSuggestions); } /** * Get intent-specific suggestions */ private getIntentSpecificSuggestions(intent: Intent, _context: ResponseContext): string[] { const suggestions: Record<Intent, string[]> = { 'create_project': ['Add tasks to your project', 'Set project priorities', 'Invite team members'], 'update_project': ['Modify project settings', 'Change project configuration', 'Update project details'], 'create_task': ['Run the task', 'Set task dependencies', 'Assign the task'], 'list_projects': ['Create a new project', 'Check project status', 'Archive old projects'], 'list_tasks': ['Create a new task', 'Run a task', 'Update task status'], 'run_task': ['Check task progress', 'View execution logs', 'Stop task execution'], 'check_status': ['Update project status', 'View detailed reports', 'Set status alerts'], 'decompose_task': ['Review subtasks', 'Assign subtasks', 'Set task priorities'], 'decompose_epic': ['Review epic tasks', 'Set task priorities', 'Assign tasks to developers'], 'decompose_project': ['Review project breakdown', 'Create epics', 'Set project priorities'], 'search_files': ['Search for content', 'List all files', 'Open a file'], 'search_content': ['Search for files', 'Show file details', 'Edit a file'], 'refine_task': ['Update task description', 'Set acceptance criteria', 'Add task notes'], 'assign_task': ['Set task deadlines', 'Add task comments', 'Track assignment'], 'get_help': ['View command examples', 'Check documentation', 'Contact support'], 'open_project': ['View project details', 'Edit project settings', 'Add project members'], 'parse_prd': ['Generate epics from PRD', 'Create tasks from features', 'Review PRD content'], 'parse_tasks': ['Execute task list', 'Review task dependencies', 'Assign tasks to agents'], 'import_artifact': ['Parse specific artifact type', 'Review imported content', 'Create project from artifact'], 'unrecognized_intent': ['Try being more specific', 'Ask for help', 'View available commands'], 'clarification_needed': ['Provide more details', 'Be more specific', 'Try a different approach'], 'unknown': ['Try a different command', 'Ask for help', 'View available commands'] }; return suggestions[intent] || []; } /** * Get error suggestions for specific intents */ private getErrorSuggestionsForIntent(intent: Intent): string[] { const errorSuggestions: Partial<Record<Intent, string[]>> = { 'create_project': ['Provide a project name', 'Check project name format'], 'create_task': ['Specify task details', 'Set a project context'], 'run_task': ['Provide a valid task ID', 'Check task status'], 'check_status': ['Specify what to check', 'Provide project or task name'] }; return errorSuggestions[intent] || []; } /** * Make error messages more helpful */ private makeErrorHelpful( errorText: string, recognizedIntent: RecognizedIntent, _context: ResponseContext ): string { let helpfulText = errorText; // Add context about what went wrong if (recognizedIntent.confidence < 0.5) { helpfulText += '\n\nI wasn\'t very confident about understanding your request. '; helpfulText += 'Could you try rephrasing it more specifically?'; } // Add examples for common errors if (errorText.includes('required')) { helpfulText += '\n\nFor example, try: "Create a project called MyApp" or "Run task 123"'; } return helpfulText; } /** * Update configuration */ updateConfig(newConfig: Partial<ResponseGeneratorConfig>): void { this.config = { ...this.config, ...newConfig }; logger.info({ config: this.config }, 'Response Generator configuration updated'); } /** * Get current configuration */ getConfig(): ResponseGeneratorConfig { return { ...this.config }; } } /** * Convenience function to get response generator instance */ export function getResponseGenerator(): ResponseGenerator { return ResponseGenerator.getInstance(); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/freshtechbro/vibe-coder-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server