UNPKG

agentic-data-stack-community

Version:

AI Agentic Data Stack Framework - Community Edition. Open source data engineering framework with 4 core agents, essential templates, and 3-dimensional quality validation.

1,263 lines (1,091 loc) • 41.8 kB
/** * Knowledge Base Integration System * * Implements advanced knowledge management with: * - Dynamic knowledge base loading and indexing * - Contextual knowledge retrieval and search * - Technical preferences and personalization * - Interactive KB mode with guided exploration * - Multi-source knowledge aggregation * - Version-aware documentation management * - Agent-specific knowledge filtering * - Real-time knowledge updates and caching */ const chalk = require('chalk'); const inquirer = require('inquirer'); const fs = require('fs-extra'); const path = require('path'); const yaml = require('yaml'); class KnowledgeBase { constructor(options = {}) { this.rootDir = options.rootDir || process.cwd(); this.dataCore = path.join(this.rootDir, 'data-core'); this.kbPath = path.join(this.dataCore, 'data'); this.docsPath = path.join(this.rootDir, 'docs'); this.knowledgeIndex = new Map(); this.searchIndex = new Map(); this.technicalPreferences = new Map(); this.sessionContext = new Map(); this.cacheTimeout = options.cacheTimeout || 3600000; // 1 hour this.lastIndexTime = null; this.agentOrchestrator = options.agentOrchestrator; this.documentManager = options.documentManager; } /** * Initialize knowledge base and load core data */ async initialize() { console.log(chalk.blue('🧠 Initializing Knowledge Base...')); try { // Load core knowledge documents await this.loadCoreKnowledge(); // Load technical preferences await this.loadTechnicalPreferences(); // Build search index await this.buildSearchIndex(); // Load project-specific documentation await this.loadProjectDocumentation(); console.log(chalk.green('āœ… Knowledge Base initialized successfully')); return { success: true, documentsLoaded: this.knowledgeIndex.size }; } catch (error) { console.error(chalk.red(`āŒ Knowledge Base initialization failed: ${error.message}`)); return { success: false, error: error.message }; } } /** * Load core knowledge documents from data-core */ async loadCoreKnowledge() { const coreFiles = [ 'bmad-kb.md', 'elicitation-methods.md', 'brainstorming-techniques.md', 'technical-preferences.md' ]; for (const file of coreFiles) { const filePath = path.join(this.kbPath, file); if (await fs.pathExists(filePath)) { const content = await fs.readFile(filePath, 'utf8'); const metadata = this.extractMetadata(content); this.knowledgeIndex.set(file, { path: filePath, content, metadata, type: 'core', lastModified: (await fs.stat(filePath)).mtime, category: this.categorizeDocument(file, content) }); } } // Load additional knowledge files from data directory if (await fs.pathExists(this.kbPath)) { const files = await fs.readdir(this.kbPath); for (const file of files) { if (file.endsWith('.md') && !coreFiles.includes(file)) { await this.loadKnowledgeFile(path.join(this.kbPath, file), 'data'); } } } } /** * Load a knowledge file and index it */ async loadKnowledgeFile(filePath, type = 'custom') { try { const content = await fs.readFile(filePath, 'utf8'); const fileName = path.basename(filePath); const metadata = this.extractMetadata(content); this.knowledgeIndex.set(fileName, { path: filePath, content, metadata, type, lastModified: (await fs.stat(filePath)).mtime, category: this.categorizeDocument(fileName, content) }); } catch (error) { console.warn(chalk.yellow(`Warning: Could not load ${filePath}: ${error.message}`)); } } /** * Load technical preferences */ async loadTechnicalPreferences() { const prefsPath = path.join(this.kbPath, 'technical-preferences.md'); if (await fs.pathExists(prefsPath)) { const content = await fs.readFile(prefsPath, 'utf8'); const preferences = this.parseTechnicalPreferences(content); preferences.forEach(pref => { this.technicalPreferences.set(pref.category, pref); }); } // Load user-specific preferences if available const userPrefsPath = path.join(this.rootDir, '.technical-preferences.yaml'); if (await fs.pathExists(userPrefsPath)) { try { const userPrefs = await fs.readFile(userPrefsPath, 'utf8'); const parsed = yaml.parse(userPrefs); Object.entries(parsed).forEach(([category, prefs]) => { this.technicalPreferences.set(category, { category, preferences: prefs, source: 'user' }); }); } catch (error) { console.warn(chalk.yellow('Warning: Could not parse user preferences')); } } } /** * Parse technical preferences from markdown */ parseTechnicalPreferences(content) { const preferences = []; const lines = content.split('\n'); let currentCategory = null; let currentPrefs = []; for (const line of lines) { if (line.startsWith('## ')) { if (currentCategory && currentPrefs.length > 0) { preferences.push({ category: currentCategory, preferences: currentPrefs, source: 'default' }); } currentCategory = line.replace('## ', '').trim(); currentPrefs = []; } else if (line.trim().startsWith('- ')) { currentPrefs.push(line.trim().substring(2)); } } if (currentCategory && currentPrefs.length > 0) { preferences.push({ category: currentCategory, preferences: currentPrefs, source: 'default' }); } return preferences; } /** * Build search index for fast retrieval */ async buildSearchIndex() { console.log(chalk.dim('Building search index...')); this.knowledgeIndex.forEach((doc, fileName) => { // Extract searchable terms const terms = this.extractSearchTerms(doc.content); terms.forEach(term => { if (!this.searchIndex.has(term)) { this.searchIndex.set(term, []); } this.searchIndex.get(term).push(fileName); }); // Index metadata if (doc.metadata.tags) { doc.metadata.tags.forEach(tag => { const tagKey = `tag:${tag}`; if (!this.searchIndex.has(tagKey)) { this.searchIndex.set(tagKey, []); } this.searchIndex.get(tagKey).push(fileName); }); } }); this.lastIndexTime = new Date(); } /** * Extract search terms from content */ extractSearchTerms(content) { const terms = new Set(); // Extract words (alphanumeric, minimum 3 characters) const words = content.toLowerCase().match(/\b[a-z0-9]{3,}\b/g) || []; words.forEach(word => terms.add(word)); // Extract headings const headings = content.match(/^#{1,6}\s+(.+)$/gm) || []; headings.forEach(heading => { const clean = heading.replace(/^#{1,6}\s+/, '').toLowerCase(); terms.add(clean); // Also add individual words from headings clean.split(/\s+/).forEach(word => { if (word.length >= 3) terms.add(word); }); }); // Extract code identifiers const codeBlocks = content.match(/`([^`]+)`/g) || []; codeBlocks.forEach(block => { const identifier = block.replace(/`/g, '').toLowerCase(); if (identifier.length >= 3) terms.add(identifier); }); return Array.from(terms); } /** * Extract metadata from document content */ extractMetadata(content) { const metadata = { title: '', description: '', tags: [], category: '', lastUpdated: null }; // Extract title from first H1 const titleMatch = content.match(/^#\s+(.+)$/m); if (titleMatch) { metadata.title = titleMatch[1]; } // Extract description from overview section or first paragraph const overviewMatch = content.match(/##\s+Overview\s*\n\n([^\n]+)/); if (overviewMatch) { metadata.description = overviewMatch[1]; } else { const firstParaMatch = content.match(/^#[^\n]+\n\n([^\n]+)/); if (firstParaMatch) { metadata.description = firstParaMatch[1]; } } // Extract tags from content patterns if (content.includes('workflow')) metadata.tags.push('workflow'); if (content.includes('template')) metadata.tags.push('template'); if (content.includes('agent')) metadata.tags.push('agent'); if (content.includes('development')) metadata.tags.push('development'); if (content.includes('configuration')) metadata.tags.push('configuration'); return metadata; } /** * Categorize document based on content */ categorizeDocument(fileName, content) { const fileNameLower = fileName.toLowerCase(); const contentLower = content.toLowerCase(); if (fileNameLower.includes('install') || contentLower.includes('installation')) { return 'setup'; } else if (fileNameLower.includes('workflow')) { return 'workflows'; } else if (fileNameLower.includes('agent') || contentLower.includes('## agents')) { return 'agents'; } else if (fileNameLower.includes('template') || fileNameLower.includes('prd') || fileNameLower.includes('architecture')) { return 'documents'; } else if (contentLower.includes('agile') || contentLower.includes('scrum')) { return 'agile'; } else if (fileNameLower.includes('config') || contentLower.includes('configuration')) { return 'configuration'; } else if (fileNameLower.includes('best') || fileNameLower.includes('practice')) { return 'best-practices'; } else { return 'general'; } } /** * Load project-specific documentation */ async loadProjectDocumentation() { if (!await fs.pathExists(this.docsPath)) { return; } const docFiles = await this.findMarkdownFiles(this.docsPath); for (const file of docFiles) { await this.loadKnowledgeFile(file, 'project'); } } /** * Recursively find markdown files */ async findMarkdownFiles(dir, files = []) { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory() && !entry.name.startsWith('.')) { await this.findMarkdownFiles(fullPath, files); } else if (entry.isFile() && entry.name.endsWith('.md')) { files.push(fullPath); } } return files; } /** * Interactive KB mode interface */ async enterKBMode(context = {}) { console.log(chalk.bold.blue('\n🧠 Knowledge Base Mode Activated')); console.log(chalk.dim('Access to comprehensive framework knowledge and project documentation\n')); const topicAreas = [ 'Setup & Installation - Getting started with the framework', 'Workflows - Choosing the right workflow for your project', 'Web vs IDE - When to use each environment', 'Agents - Understanding specialized agents and their roles', 'Documents - PRDs, Architecture, Stories, and more', 'Agile Process - How the framework implements Agile methodologies', 'Configuration - Customizing the framework for your needs', 'Best Practices - Tips for effective framework usage', 'Technical Preferences - View and update your preferences', 'Search Knowledge Base - Find specific information', 'Exit KB Mode' ]; let continueKBMode = true; while (continueKBMode) { console.log(chalk.bold('\nWhat would you like to know more about?\n')); const { topic } = await inquirer.prompt([{ type: 'list', name: 'topic', message: 'Select a topic:', choices: topicAreas.map((area, index) => ({ name: `${index + 1}. ${area}`, value: index })) }]); switch (topic) { case 0: // Setup & Installation await this.showTopicKnowledge('setup', 'Setup & Installation'); break; case 1: // Workflows await this.showTopicKnowledge('workflows', 'Workflows'); break; case 2: // Web vs IDE await this.showEnvironmentComparison(); break; case 3: // Agents await this.showAgentKnowledge(); break; case 4: // Documents await this.showDocumentKnowledge(); break; case 5: // Agile Process await this.showTopicKnowledge('agile', 'Agile Process'); break; case 6: // Configuration await this.showConfigurationKnowledge(); break; case 7: // Best Practices await this.showTopicKnowledge('best-practices', 'Best Practices'); break; case 8: // Technical Preferences await this.manageTechnicalPreferences(); break; case 9: // Search await this.interactiveSearch(); break; case 10: // Exit continueKBMode = false; break; } if (continueKBMode && topic !== 10) { const { continueExploring } = await inquirer.prompt([{ type: 'confirm', name: 'continueExploring', message: 'Would you like to explore another topic?', default: true }]); continueKBMode = continueExploring; } } console.log(chalk.green('\nāœ… Exiting Knowledge Base Mode')); console.log(chalk.dim('You can return anytime with *kb-mode')); return { success: true, mode: 'exited' }; } /** * Show knowledge for a specific topic category */ async showTopicKnowledge(category, title) { console.log(chalk.bold.blue(`\nšŸ“š ${title}\n`)); const relevantDocs = Array.from(this.knowledgeIndex.entries()) .filter(([_, doc]) => doc.category === category) .map(([fileName, doc]) => ({ fileName, ...doc })); if (relevantDocs.length === 0) { // Search for content containing the category const searchResults = await this.search(category); if (searchResults.length > 0) { console.log(chalk.yellow(`Found ${searchResults.length} related documents:\n`)); await this.displaySearchResults(searchResults); } else { console.log(chalk.yellow('No specific documents found for this category.')); console.log(chalk.dim('Try searching for specific terms or check other categories.')); } return; } // Display summary of available documents console.log(chalk.bold('Available Resources:')); relevantDocs.forEach((doc, index) => { console.log(`\n${index + 1}. ${chalk.bold(doc.metadata.title || doc.fileName)}`); if (doc.metadata.description) { console.log(chalk.dim(` ${doc.metadata.description}`)); } }); // Allow user to select specific document if (relevantDocs.length > 1) { const { selectedDoc } = await inquirer.prompt([{ type: 'list', name: 'selectedDoc', message: 'Select a document to view:', choices: [ ...relevantDocs.map((doc, index) => ({ name: doc.metadata.title || doc.fileName, value: index })), { name: 'View All Summaries', value: -1 }, { name: 'Back to Topics', value: -2 } ] }]); if (selectedDoc >= 0) { await this.displayDocument(relevantDocs[selectedDoc]); } else if (selectedDoc === -1) { for (const doc of relevantDocs) { await this.displayDocumentSummary(doc); } } } else if (relevantDocs.length === 1) { await this.displayDocument(relevantDocs[0]); } } /** * Show environment comparison (Web vs IDE) */ async showEnvironmentComparison() { console.log(chalk.bold.blue('\n🌐 Web UI vs šŸ’» IDE Environment\n')); console.log(chalk.bold('Web UI Best For:')); console.log(chalk.green('• Initial planning and documentation phases')); console.log(chalk.green('• Cost-effective large document creation (especially Gemini)')); console.log(chalk.green('• Multi-agent consultation and brainstorming')); console.log(chalk.green('• Projects without local file access needs')); console.log(chalk.bold('\nIDE Best For:')); console.log(chalk.blue('• Active development and implementation')); console.log(chalk.blue('• File operations and project integration')); console.log(chalk.blue('• Document sharding and story management')); console.log(chalk.blue('• Real-time code editing and testing')); console.log(chalk.bold('\nCost-Saving Strategy:')); console.log(chalk.yellow('1. Create large documents (PRD, Architecture) in Web UI')); console.log(chalk.yellow('2. Copy to project as docs/prd.md and docs/architecture.md')); console.log(chalk.yellow('3. Switch to IDE for development workflow')); console.log(chalk.yellow('4. Use sharding to break documents into manageable pieces')); const { learnMore } = await inquirer.prompt([{ type: 'confirm', name: 'learnMore', message: 'Would you like to learn about specific environment setup?', default: false }]); if (learnMore) { const { environment } = await inquirer.prompt([{ type: 'list', name: 'environment', message: 'Which environment?', choices: ['Web UI Setup', 'IDE Setup', 'Migration Between Environments'] }]); // Show relevant documentation const searchTerm = environment.toLowerCase().replace(' setup', ''); const results = await this.search(searchTerm); if (results.length > 0) { await this.displaySearchResults(results.slice(0, 3)); } } } /** * Show agent knowledge */ async showAgentKnowledge() { console.log(chalk.bold.blue('\nšŸ¤– Agent System Overview\n')); const agentCategories = { 'Core Development Team': [ { id: 'analyst', name: 'Business Analyst', role: 'Market research, requirements gathering' }, { id: 'pm', name: 'Product Manager', role: 'PRD creation, feature prioritization' }, { id: 'architect', name: 'Solution Architect', role: 'System design, technical architecture' }, { id: 'dev', name: 'Developer', role: 'Code implementation, debugging' }, { id: 'qa', name: 'QA Specialist', role: 'Test planning, quality assurance' }, { id: 'ux-expert', name: 'UX Designer', role: 'UI/UX design, prototypes' }, { id: 'po', name: 'Product Owner', role: 'Backlog management, story validation' }, { id: 'sm', name: 'Scrum Master', role: 'Sprint planning, story creation' } ], 'Meta Agents': [ { id: 'bmad-orchestrator', name: 'Team Coordinator', role: 'Multi-agent workflows, role switching' }, { id: 'bmad-master', name: 'Universal Expert', role: 'All capabilities without switching' } ] }; console.log(chalk.bold('Available Agents by Category:\n')); Object.entries(agentCategories).forEach(([category, agents]) => { console.log(chalk.bold.yellow(category + ':')); agents.forEach(agent => { console.log(` ${chalk.green(agent.id)} - ${agent.name}`); console.log(chalk.dim(` ${agent.role}`)); }); console.log(''); }); const { agentAction } = await inquirer.prompt([{ type: 'list', name: 'agentAction', message: 'What would you like to do?', choices: [ 'Learn about a specific agent', 'View agent activation commands', 'Understand agent collaboration', 'Back to topics' ] }]); switch (agentAction) { case 'Learn about a specific agent': await this.showSpecificAgentDetails(); break; case 'View agent activation commands': await this.showAgentCommands(); break; case 'Understand agent collaboration': await this.showAgentCollaboration(); break; } } /** * Display document content with formatting */ async displayDocument(doc) { console.log(chalk.bold.blue(`\nšŸ“„ ${doc.metadata.title || doc.fileName}\n`)); // Display content in sections const sections = this.splitIntoSections(doc.content); for (const section of sections) { console.log(chalk.bold(section.title)); console.log(section.content); if (sections.indexOf(section) < sections.length - 1) { const { continueReading } = await inquirer.prompt([{ type: 'confirm', name: 'continueReading', message: 'Continue reading?', default: true }]); if (!continueReading) break; } } } /** * Display document summary */ async displayDocumentSummary(doc) { console.log(chalk.bold(`\nšŸ“„ ${doc.metadata.title || doc.fileName}`)); if (doc.metadata.description) { console.log(chalk.dim(doc.metadata.description)); } console.log(chalk.dim(`Type: ${doc.type} | Category: ${doc.category}`)); console.log(''); } /** * Split content into readable sections */ splitIntoSections(content) { const sections = []; const lines = content.split('\n'); let currentSection = { title: 'Introduction', content: '' }; for (const line of lines) { if (line.match(/^#{1,2}\s+(.+)$/)) { if (currentSection.content.trim()) { sections.push(currentSection); } currentSection = { title: line, content: '' }; } else { currentSection.content += line + '\n'; } } if (currentSection.content.trim()) { sections.push(currentSection); } return sections; } /** * Interactive search interface */ async interactiveSearch() { console.log(chalk.bold.blue('\nšŸ” Knowledge Base Search\n')); const { searchQuery } = await inquirer.prompt([{ type: 'input', name: 'searchQuery', message: 'Enter search terms:', validate: input => input.trim().length >= 2 || 'Please enter at least 2 characters' }]); const results = await this.search(searchQuery); if (results.length === 0) { console.log(chalk.yellow('No results found. Try different search terms.')); return; } console.log(chalk.green(`\nFound ${results.length} results:\n`)); await this.displaySearchResults(results); } /** * Search knowledge base */ async search(query, options = {}) { const queryLower = query.toLowerCase(); const words = queryLower.split(/\s+/); const results = new Map(); // Search in index words.forEach(word => { if (this.searchIndex.has(word)) { this.searchIndex.get(word).forEach(fileName => { if (!results.has(fileName)) { results.set(fileName, { fileName, score: 0, matches: [] }); } results.get(fileName).score += 1; results.get(fileName).matches.push(word); }); } }); // Search in content this.knowledgeIndex.forEach((doc, fileName) => { const contentLower = doc.content.toLowerCase(); let contentScore = 0; words.forEach(word => { const occurrences = (contentLower.match(new RegExp(word, 'g')) || []).length; if (occurrences > 0) { contentScore += occurrences; if (!results.has(fileName)) { results.set(fileName, { fileName, score: 0, matches: [] }); } results.get(fileName).score += occurrences; if (!results.get(fileName).matches.includes(word)) { results.get(fileName).matches.push(word); } } }); // Boost score for title matches if (doc.metadata.title && doc.metadata.title.toLowerCase().includes(queryLower)) { if (!results.has(fileName)) { results.set(fileName, { fileName, score: 0, matches: [] }); } results.get(fileName).score += 10; } }); // Sort by score and return const sortedResults = Array.from(results.values()) .sort((a, b) => b.score - a.score) .slice(0, options.limit || 10); return sortedResults.map(result => ({ ...result, document: this.knowledgeIndex.get(result.fileName) })); } /** * Display search results */ async displaySearchResults(results) { results.forEach((result, index) => { const doc = result.document; console.log(`${index + 1}. ${chalk.bold(doc.metadata.title || result.fileName)}`); console.log(chalk.dim(` Score: ${result.score} | Matches: ${result.matches.join(', ')}`)); if (doc.metadata.description) { console.log(chalk.dim(` ${doc.metadata.description.substring(0, 100)}...`)); } console.log(''); }); if (results.length > 0) { const { viewDoc } = await inquirer.prompt([{ type: 'list', name: 'viewDoc', message: 'Select a document to view:', choices: [ ...results.map((result, index) => ({ name: result.document.metadata.title || result.fileName, value: index })), { name: 'Back to search', value: -1 } ] }]); if (viewDoc >= 0) { await this.displayDocument(results[viewDoc].document); } } } /** * Manage technical preferences */ async manageTechnicalPreferences() { console.log(chalk.bold.blue('\nāš™ļø Technical Preferences\n')); if (this.technicalPreferences.size === 0) { console.log(chalk.yellow('No technical preferences configured yet.')); const { addPrefs } = await inquirer.prompt([{ type: 'confirm', name: 'addPrefs', message: 'Would you like to add technical preferences?', default: true }]); if (addPrefs) { await this.addTechnicalPreferences(); } return; } console.log(chalk.bold('Current Preferences:\n')); this.technicalPreferences.forEach((pref, category) => { console.log(chalk.bold.yellow(`${category}:`)); pref.preferences.forEach(item => { console.log(chalk.green(` • ${item}`)); }); console.log(''); }); const { action } = await inquirer.prompt([{ type: 'list', name: 'action', message: 'What would you like to do?', choices: [ 'Add new category', 'Edit existing category', 'Remove category', 'Save preferences', 'Back to topics' ] }]); switch (action) { case 'Add new category': await this.addTechnicalPreferences(); break; case 'Edit existing category': await this.editTechnicalPreferences(); break; case 'Remove category': await this.removeTechnicalPreferences(); break; case 'Save preferences': await this.saveTechnicalPreferences(); break; } } /** * Add technical preferences */ async addTechnicalPreferences() { const categories = [ 'Frontend Framework', 'Backend Language', 'Database', 'Testing Framework', 'Build Tools', 'Deployment', 'Custom Category' ]; const { category } = await inquirer.prompt([{ type: 'list', name: 'category', message: 'Select preference category:', choices: categories }]); const finalCategory = category === 'Custom Category' ? (await inquirer.prompt([{ type: 'input', name: 'custom', message: 'Enter custom category name:' }])).custom : category; const { preferences } = await inquirer.prompt([{ type: 'input', name: 'preferences', message: `Enter ${finalCategory} preferences (comma-separated):`, validate: input => input.trim().length > 0 || 'Please enter at least one preference' }]); this.technicalPreferences.set(finalCategory, { category: finalCategory, preferences: preferences.split(',').map(p => p.trim()), source: 'user' }); console.log(chalk.green(`āœ… Added preferences for ${finalCategory}`)); } /** * Save technical preferences to file */ async saveTechnicalPreferences() { const userPrefs = {}; this.technicalPreferences.forEach((pref, category) => { if (pref.source === 'user') { userPrefs[category] = pref.preferences; } }); const prefsPath = path.join(this.rootDir, '.technical-preferences.yaml'); await fs.writeFile(prefsPath, yaml.stringify(userPrefs), 'utf8'); console.log(chalk.green(`āœ… Preferences saved to ${prefsPath}`)); } /** * Get context-aware knowledge */ async getContextualKnowledge(context = {}) { const { agent, task, topic } = context; const relevant = []; // Filter by agent if specified if (agent) { this.knowledgeIndex.forEach((doc, fileName) => { if (doc.content.toLowerCase().includes(agent.toLowerCase()) || (doc.metadata.tags && doc.metadata.tags.includes('agent'))) { relevant.push({ fileName, ...doc, relevance: 'agent' }); } }); } // Filter by task if specified if (task) { const taskResults = await this.search(task, { limit: 5 }); taskResults.forEach(result => { relevant.push({ ...result.document, relevance: 'task' }); }); } // Filter by topic if specified if (topic) { const topicDocs = Array.from(this.knowledgeIndex.entries()) .filter(([_, doc]) => doc.category === topic) .map(([fileName, doc]) => ({ fileName, ...doc, relevance: 'topic' })); relevant.push(...topicDocs); } return relevant; } /** * Get agent-specific knowledge */ async getAgentKnowledge(agentId) { const agentKnowledge = { general: [], tasks: [], templates: [], workflows: [] }; this.knowledgeIndex.forEach((doc, fileName) => { const contentLower = doc.content.toLowerCase(); const agentLower = agentId.toLowerCase(); if (contentLower.includes(agentLower)) { if (fileName.includes('task')) { agentKnowledge.tasks.push({ fileName, ...doc }); } else if (fileName.includes('template')) { agentKnowledge.templates.push({ fileName, ...doc }); } else if (fileName.includes('workflow')) { agentKnowledge.workflows.push({ fileName, ...doc }); } else { agentKnowledge.general.push({ fileName, ...doc }); } } }); return agentKnowledge; } /** * Update knowledge base with new information */ async updateKnowledge(fileName, content, metadata = {}) { const filePath = path.join(this.kbPath, fileName); try { await fs.writeFile(filePath, content, 'utf8'); this.knowledgeIndex.set(fileName, { path: filePath, content, metadata: { ...this.extractMetadata(content), ...metadata }, type: 'custom', lastModified: new Date(), category: this.categorizeDocument(fileName, content) }); // Rebuild search index await this.buildSearchIndex(); console.log(chalk.green(`āœ… Knowledge base updated: ${fileName}`)); return { success: true, fileName }; } catch (error) { console.error(chalk.red(`āŒ Failed to update knowledge: ${error.message}`)); return { success: false, error: error.message }; } } /** * Export knowledge for agent consumption */ async exportForAgent(agentId, format = 'markdown') { const agentKnowledge = await this.getAgentKnowledge(agentId); let exportContent = ''; if (format === 'markdown') { exportContent = `# Knowledge Base for ${agentId}\n\n`; Object.entries(agentKnowledge).forEach(([category, docs]) => { if (docs.length > 0) { exportContent += `## ${category.charAt(0).toUpperCase() + category.slice(1)}\n\n`; docs.forEach(doc => { exportContent += `### ${doc.metadata.title || doc.fileName}\n\n`; exportContent += doc.content + '\n\n---\n\n'; }); } }); } else if (format === 'json') { exportContent = JSON.stringify(agentKnowledge, null, 2); } return exportContent; } /** * Show specific agent details */ async showSpecificAgentDetails() { const agents = [ 'analyst', 'pm', 'architect', 'dev', 'qa', 'ux-expert', 'po', 'sm', 'orchestrator', 'master' ]; const { selectedAgent } = await inquirer.prompt([{ type: 'list', name: 'selectedAgent', message: 'Select an agent to learn about:', choices: agents }]); const agentKnowledge = await this.getAgentKnowledge(selectedAgent); console.log(chalk.bold.blue(`\nšŸ¤– ${selectedAgent.toUpperCase()} Agent Details\n`)); if (agentKnowledge.general.length > 0) { const doc = agentKnowledge.general[0]; const excerpt = doc.content.substring(0, 500) + '...'; console.log(excerpt); } if (agentKnowledge.tasks.length > 0) { console.log(chalk.bold('\nAvailable Tasks:')); agentKnowledge.tasks.forEach(task => { console.log(` • ${task.metadata.title || task.fileName}`); }); } if (agentKnowledge.templates.length > 0) { console.log(chalk.bold('\nAvailable Templates:')); agentKnowledge.templates.forEach(template => { console.log(` • ${template.metadata.title || template.fileName}`); }); } } /** * Show agent activation commands */ async showAgentCommands() { console.log(chalk.bold.blue('\nšŸ’» Agent Activation Commands\n')); console.log(chalk.bold('IDE-Specific Syntax:')); console.log(chalk.green('• Claude Code: /agent-name (e.g., /dev)')); console.log(chalk.green('• Cursor: @agent-name (e.g., @dev)')); console.log(chalk.green('• Windsurf: @agent-name (e.g., @dev)')); console.log(chalk.green('• VS Code with Cline: Select from mode selector')); console.log(chalk.green('• Roo Code: Select from mode selector')); console.log(chalk.bold('\nCommon Commands:')); console.log(chalk.blue('• *help - Show available commands')); console.log(chalk.blue('• *status - Show current context/progress')); console.log(chalk.blue('• *exit - Exit the agent mode')); console.log(chalk.blue('• *task <name> - Execute a specific task')); console.log(chalk.blue('• *create-doc <template> - Create document from template')); console.log(chalk.bold('\nWeb UI Commands:')); console.log(chalk.yellow('• /help - Show available commands')); console.log(chalk.yellow('• /switch <agent> - Change active agent')); console.log(chalk.yellow('• /pm create-doc prd - Create PRD with PM agent')); } /** * Show agent collaboration patterns */ async showAgentCollaboration() { console.log(chalk.bold.blue('\nšŸ¤ Agent Collaboration Patterns\n')); console.log(chalk.bold('Development Workflow:')); console.log(chalk.green('1. SM Agent → Creates next story from sharded docs')); console.log(chalk.green('2. You → Review and approve story')); console.log(chalk.green('3. Dev Agent → Implements approved story')); console.log(chalk.green('4. QA Agent → Reviews and refactors code')); console.log(chalk.green('5. You → Verify completion')); console.log(chalk.green('6. Repeat until epic complete')); console.log(chalk.bold('\nKey Principles:')); console.log(chalk.blue('• Clean Handoffs - Always start fresh when switching agents')); console.log(chalk.blue('• Agent Specialization - Each agent has specific expertise')); console.log(chalk.blue('• Sequential Progress - One story at a time')); console.log(chalk.blue('• Human Oversight - You validate each step')); console.log(chalk.bold('\nCritical Rules:')); console.log(chalk.red('• ALWAYS use SM agent for story creation')); console.log(chalk.red('• ALWAYS use Dev agent for implementation')); console.log(chalk.red('• NEVER use master/orchestrator for dev workflow')); } /** * Show document knowledge and templates */ async showDocumentKnowledge() { console.log(chalk.bold.blue('\nšŸ“„ Document System Overview\n')); const documentTypes = { 'Planning Documents': [ { name: 'PRD (Product Requirements)', file: 'docs/prd.md', template: 'prd-tmpl' }, { name: 'Architecture Specification', file: 'docs/architecture.md', template: 'architecture-tmpl' }, { name: 'Project Brief', file: 'docs/brief.md', template: 'project-brief-tmpl' } ], 'Development Documents': [ { name: 'User Stories', file: 'docs/stories/*.md', template: 'story-tmpl' }, { name: 'Technical Specs', file: 'docs/specs/*.md', template: 'tech-spec-tmpl' }, { name: 'API Documentation', file: 'docs/api/*.md', template: 'api-doc-tmpl' } ], 'Analysis Documents': [ { name: 'Market Research', file: 'docs/research.md', template: 'market-research-tmpl' }, { name: 'Competitive Analysis', file: 'docs/competitive.md', template: 'competitor-analysis-tmpl' }, { name: 'Requirements Analysis', file: 'docs/requirements.md', template: 'requirements-tmpl' } ] }; console.log(chalk.bold('Document Types and Templates:\n')); Object.entries(documentTypes).forEach(([category, docs]) => { console.log(chalk.bold.yellow(category + ':')); docs.forEach(doc => { console.log(` ${chalk.green(doc.name)}`); console.log(chalk.dim(` File: ${doc.file}`)); console.log(chalk.dim(` Template: ${doc.template}`)); }); console.log(''); }); const { docAction } = await inquirer.prompt([{ type: 'list', name: 'docAction', message: 'What would you like to learn about?', choices: [ 'Document creation workflow', 'Document sharding process', 'Template system', 'Back to topics' ] }]); switch (docAction) { case 'Document creation workflow': console.log(chalk.bold('\nšŸ“ Document Creation Workflow:')); console.log('1. Use appropriate agent (PM for PRD, Architect for tech specs)'); console.log('2. Execute *create-doc command with template name'); console.log('3. Follow interactive prompts for each section'); console.log('4. Review and refine with elicitation methods'); console.log('5. Save to standard location (docs/prd.md, etc.)'); break; case 'Document sharding process': console.log(chalk.bold('\nāœ‚ļø Document Sharding:')); console.log('• Purpose: Break large documents into manageable pieces'); console.log('• Command: *shard-doc docs/prd.md'); console.log('• Creates: docs/prd/ folder with section files'); console.log('• Benefits: Better context management for dev workflow'); break; case 'Template system': console.log(chalk.bold('\nšŸ“‹ Template System:')); console.log('• YAML-based templates define document structure'); console.log('• Progressive disclosure for complex documents'); console.log('• Interactive elicitation for quality content'); console.log('• Agent-specific templates for specialized needs'); break; } } /** * Show configuration knowledge */ async showConfigurationKnowledge() { console.log(chalk.bold.blue('\nāš™ļø Configuration System\n')); console.log(chalk.bold('Core Configuration (core-config.yaml):')); console.log(chalk.green('• Version settings - Control document format versions')); console.log(chalk.green('• Sharding configuration - Define document organization')); console.log(chalk.green('• Developer files - Specify always-loaded files')); console.log(chalk.green('• Debug settings - Configure logging and diagnostics')); console.log(chalk.bold('\nKey Configuration Areas:')); console.log(chalk.blue('• PRD Configuration - Version and sharding settings')); console.log(chalk.blue('• Architecture Configuration - Document structure')); console.log(chalk.blue('• Developer Context - Files loaded for every task')); console.log(chalk.blue('• Workflow Settings - Process customization')); const { showExample } = await inquirer.prompt([{ type: 'confirm', name: 'showExample', message: 'Would you like to see example configurations?', default: true }]); if (showExample) { console.log(chalk.bold('\nExample Configurations:\n')); console.log(chalk.yellow('Legacy V3 Project:')); console.log(chalk.dim(`prdVersion: v3 prdSharded: false architectureVersion: v3 architectureSharded: false`)); console.log(chalk.yellow('\nV4 Optimized Project:')); console.log(chalk.dim(`prdVersion: v4 prdSharded: true prdShardedLocation: docs/prd architectureVersion: v4 architectureSharded: true architectureShardedLocation: docs/architecture`)); } } } module.exports = KnowledgeBase;