Skip to main content
Glama
ContextualReferenceGenerator.ts13.2 kB
import { generateObject } from 'ai'; import { AIServiceFactory } from '../ai/AIServiceFactory'; import { ContextualReferences, PRDSectionReference, RelatedFeature, TechnicalSpecReference, CodeExample, ExternalReference } from '../../domain/task-context-schemas'; import { AITask, PRDDocument, FeatureRequirement } from '../../domain/ai-types'; import { CONTEXT_GENERATION_CONFIGS, formatContextPrompt } from '../ai/prompts/ContextGenerationPrompts'; /** * Generates contextual references for tasks (FR-4: Contextual References System) * * Provides comprehensive reference materials including: * - Relevant PRD sections with explanations * - Related features and user stories * - Technical specifications and API references * - Code examples and implementation patterns * - External documentation and resources */ export class ContextualReferenceGenerator { private aiFactory: AIServiceFactory; constructor() { this.aiFactory = AIServiceFactory.getInstance(); } /** * Generate complete contextual references for a task */ async generateReferences( task: AITask, prd: PRDDocument | string, features?: FeatureRequirement[] ): Promise<ContextualReferences | null> { try { const model = this.aiFactory.getBestAvailableModel(); if (!model) { // Fallback to manual extraction if no AI available return this.generateBasicReferences(task, prd, features); } const prdContent = typeof prd === 'string' ? prd : JSON.stringify(prd, null, 2); const config = CONTEXT_GENERATION_CONFIGS.contextualReferences; const prompt = formatContextPrompt(config.userPrompt, { prdContent, taskTitle: task.title, taskDescription: task.description }); const result = await generateObject({ model, system: config.systemPrompt, prompt, schema: config.schema, maxTokens: config.maxTokens, temperature: config.temperature }); return result.object as ContextualReferences; } catch (error) { process.stderr.write(`Error generating contextual references: ${error instanceof Error ? error.message : String(error)}\n`); // Fallback to basic references return this.generateBasicReferences(task, prd, features); } } /** * Generate basic contextual references without AI (fallback) */ private generateBasicReferences( task: AITask, prd: PRDDocument | string, features?: FeatureRequirement[] ): ContextualReferences { const prdObj = typeof prd === 'object' ? prd : null; return { prdSections: this.extractPRDSections(task, prdObj), relatedFeatures: this.identifyRelatedFeatures(task, features || []), technicalSpecs: this.extractTechnicalSpecs(task, prdObj), codeExamples: this.generateBasicCodeExamples(task), externalReferences: this.suggestExternalReferences(task) }; } /** * Extract relevant PRD sections for the task */ private extractPRDSections( task: AITask, prd: PRDDocument | null ): PRDSectionReference[] { if (!prd) { return [{ section: 'Overview', content: 'PRD content not available', relevance: 'Task is part of the overall project requirements', importance: 'medium' as const }]; } const sections: PRDSectionReference[] = []; // Extract objectives section if (prd.objectives && prd.objectives.length > 0) { const relevantObjectives = prd.objectives.slice(0, 3).join(', '); sections.push({ section: 'Business Objectives', content: relevantObjectives, relevance: 'This task supports the overall business objectives of the project', importance: 'high' as const }); } // Extract success metrics if (prd.successMetrics && prd.successMetrics.length > 0) { const metrics = prd.successMetrics.slice(0, 3).join(', '); sections.push({ section: 'Success Metrics', content: metrics, relevance: 'Task completion contributes to these measurable success criteria', importance: 'high' as const }); } // Extract technical requirements if available if (prd.technicalRequirements) { sections.push({ section: 'Technical Requirements', content: JSON.stringify(prd.technicalRequirements, null, 2).substring(0, 500), relevance: 'Technical constraints and requirements applicable to this task', importance: 'critical' as const }); } return sections; } /** * Identify features related to this task */ private identifyRelatedFeatures( task: AITask, features: FeatureRequirement[] ): RelatedFeature[] { const relatedFeatures: RelatedFeature[] = []; const taskTitleLower = task.title.toLowerCase(); const taskDescLower = task.description.toLowerCase(); for (const feature of features) { const featureTitleLower = feature.title.toLowerCase(); // Check if task title or description mentions the feature if (taskTitleLower.includes(featureTitleLower) || taskDescLower.includes(featureTitleLower)) { relatedFeatures.push({ featureId: feature.id || `feature-${features.indexOf(feature)}`, title: feature.title, relationship: 'implements' as const, context: `This task implements part of the "${feature.title}" feature` }); } } // If no direct relationships found, link to parent feature if (relatedFeatures.length === 0 && features.length > 0) { const parentFeature = features[0]; relatedFeatures.push({ featureId: parentFeature.id || 'feature-0', title: parentFeature.title, relationship: 'depends_on' as const, context: 'This task is related to the overall feature set' }); } return relatedFeatures; } /** * Extract technical specification references */ private extractTechnicalSpecs( task: AITask, prd: PRDDocument | null ): TechnicalSpecReference[] { const specs: TechnicalSpecReference[] = []; // Detect common technical patterns in task const taskText = `${task.title} ${task.description}`.toLowerCase(); if (taskText.includes('api') || taskText.includes('endpoint') || taskText.includes('rest')) { specs.push({ type: 'api_spec' as const, title: 'API Specification', description: 'RESTful API design and endpoint specifications', relevantSections: ['Authentication', 'Request/Response Format', 'Error Handling'], url: undefined }); } if (taskText.includes('database') || taskText.includes('schema') || taskText.includes('model')) { specs.push({ type: 'data_model' as const, title: 'Data Model Specification', description: 'Database schema and data model design', relevantSections: ['Entity Relationships', 'Schema Design', 'Migrations'], url: undefined }); } if (taskText.includes('ui') || taskText.includes('component') || taskText.includes('interface')) { specs.push({ type: 'design_system' as const, title: 'Design System', description: 'UI component library and design patterns', relevantSections: ['Component Guidelines', 'Styling Standards', 'Accessibility'], url: undefined }); } if (taskText.includes('architecture') || taskText.includes('service') || taskText.includes('system')) { specs.push({ type: 'architecture_doc' as const, title: 'System Architecture', description: 'Overall system architecture and design patterns', relevantSections: ['Service Architecture', 'Integration Patterns', 'Data Flow'], url: undefined }); } return specs; } /** * Generate basic code examples based on task type */ private generateBasicCodeExamples(task: AITask): CodeExample[] { const examples: CodeExample[] = []; const taskText = `${task.title} ${task.description}`.toLowerCase(); // API endpoint example if (taskText.includes('api') || taskText.includes('endpoint')) { examples.push({ title: 'API Endpoint Pattern', description: 'Example of a RESTful API endpoint implementation', language: 'typescript', snippet: `// Example API endpoint structure router.get('/api/resource/:id', async (req, res) => { try { const { id } = req.params; const resource = await service.findById(id); if (!resource) { return res.status(404).json({ error: 'Resource not found' }); } res.json(resource); } catch (error) { res.status(500).json({ error: 'Internal server error' }); } });`, explanation: 'Standard pattern for RESTful API endpoints with error handling', source: 'Best Practices' }); } // Component example if (taskText.includes('component') || taskText.includes('ui')) { examples.push({ title: 'React Component Pattern', description: 'Example of a React functional component', language: 'typescript', snippet: `import React from 'react'; interface ComponentProps { title: string; onAction: () => void; } export const Component: React.FC<ComponentProps> = ({ title, onAction }) => { return ( <div className="component"> <h2>{title}</h2> <button onClick={onAction}>Action</button> </div> ); };`, explanation: 'Functional component with TypeScript props', source: 'React Best Practices' }); } // Service layer example if (taskText.includes('service') || taskText.includes('business logic')) { examples.push({ title: 'Service Layer Pattern', description: 'Example of service class with dependency injection', language: 'typescript', snippet: `export class ResourceService { constructor(private repository: ResourceRepository) {} async create(data: CreateResourceDto): Promise<Resource> { // Validate input this.validateData(data); // Create resource const resource = await this.repository.create(data); // Emit event this.eventEmitter.emit('resource.created', resource); return resource; } private validateData(data: CreateResourceDto): void { if (!data.title || data.title.length < 3) { throw new ValidationError('Title must be at least 3 characters'); } } }`, explanation: 'Service class with validation and event emission', source: 'Clean Architecture' }); } return examples; } /** * Suggest relevant external references */ private suggestExternalReferences(task: AITask): ExternalReference[] { const references: ExternalReference[] = []; const taskText = `${task.title} ${task.description}`.toLowerCase(); // TypeScript references if (taskText.includes('typescript') || taskText.includes('type')) { references.push({ type: 'documentation' as const, title: 'TypeScript Documentation', description: 'Official TypeScript documentation and best practices', url: 'https://www.typescriptlang.org/docs/', relevance: 'Essential reference for TypeScript type safety and patterns' }); } // React references if (taskText.includes('react') || taskText.includes('component')) { references.push({ type: 'documentation' as const, title: 'React Documentation', description: 'Official React documentation and hooks guide', url: 'https://react.dev/', relevance: 'Comprehensive guide for React components and hooks' }); } // Node.js references if (taskText.includes('node') || taskText.includes('server') || taskText.includes('api')) { references.push({ type: 'documentation' as const, title: 'Node.js Best Practices', description: 'Node.js production best practices', url: 'https://github.com/goldbergyoni/nodebestpractices', relevance: 'Production-ready Node.js patterns and practices' }); } // Testing references if (taskText.includes('test') || taskText.includes('testing')) { references.push({ type: 'best_practice' as const, title: 'Testing Best Practices', description: 'Comprehensive testing strategies and patterns', url: 'https://martinfowler.com/testing/', relevance: 'Essential testing patterns and strategies' }); } // Security references if (taskText.includes('security') || taskText.includes('auth')) { references.push({ type: 'best_practice' as const, title: 'OWASP Top 10', description: 'Top 10 security risks and mitigation strategies', url: 'https://owasp.org/www-project-top-ten/', relevance: 'Critical security considerations for web applications' }); } return references; } /** * Check if AI-enhanced references are available */ isAIAvailable(): boolean { return !!this.aiFactory.getBestAvailableModel(); } }

Latest Blog Posts

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/kunwarVivek/mcp-github-project-manager'

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