UNPKG

@hivetechs/hive-ai

Version:

Real-time streaming AI consensus platform with HTTP+SSE MCP integration for Claude Code, VS Code, Cursor, and Windsurf - powered by OpenRouter's unified API

839 lines (836 loc) β€’ 38.3 kB
import { z } from 'zod'; import * as fs from 'fs'; import * as path from 'path'; // Project Management Service class ProjectManager { projectsDir; configFile; constructor() { this.projectsDir = path.join(process.cwd(), '.hive', 'projects'); this.configFile = path.join(this.projectsDir, 'config.json'); this.ensureDirectories(); } ensureDirectories() { if (!fs.existsSync(this.projectsDir)) { fs.mkdirSync(this.projectsDir, { recursive: true }); } } async initializeProject(name, description) { const projectId = this.generateProjectId(name); const project = { id: projectId, name, description: description || '', status: 'active', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), config: { consensusEnabled: true, costTracking: true, automationLevel: 'assisted', notifications: true }, tasks: [], dependencies: [], analytics: { totalTasks: 0, completedTasks: 0, progress: 0, estimatedCost: 0, actualCost: 0, velocityMetrics: { tasksPerWeek: 0, averageTaskDuration: 0, completionRate: 0, blockerFrequency: 0 } } }; await this.saveProject(project); return project; } async parsePRD(filePath, projectId) { if (!fs.existsSync(filePath)) { throw new Error(`PRD file not found: ${filePath}`); } const prdContent = fs.readFileSync(filePath, 'utf8'); // Use consensus pipeline for PRD analysis const consensusRequest = ` Analyze this Product Requirements Document and break it down into specific, actionable development tasks: ${prdContent} Please provide: 1. A list of development tasks with clear titles and descriptions 2. Task priorities (critical, high, medium, low) 3. Estimated complexity/effort for each task 4. Dependencies between tasks 5. Risk assessment for each task Format as structured data that can be converted to project tasks. `; // This would integrate with the existing consensus system const tasks = await this.generateTasksFromConsensus(consensusRequest, projectId); return tasks; } async generateTasksFromConsensus(request, projectId) { // Mock implementation - in real implementation, this would use the 4-stage consensus pipeline const mockTasks = [ { id: this.generateTaskId(), title: "Set up project architecture", description: "Initialize project structure, configure build tools, and set up development environment", status: 'todo', priority: 'high', estimatedHours: 8, tags: ['setup', 'architecture'], dependencies: [], subtasks: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }, { id: this.generateTaskId(), title: "Implement core authentication", description: "Create user authentication system with login, registration, and session management", status: 'todo', priority: 'critical', estimatedHours: 16, tags: ['auth', 'security'], dependencies: [], subtasks: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() } ]; return mockTasks; } async getProject(projectId) { const projectPath = path.join(this.projectsDir, `${projectId}.json`); if (!fs.existsSync(projectPath)) { return null; } const projectData = fs.readFileSync(projectPath, 'utf8'); return JSON.parse(projectData); } async getAllProjects() { if (!fs.existsSync(this.projectsDir)) { return []; } const files = fs.readdirSync(this.projectsDir) .filter(file => file.endsWith('.json') && file !== 'config.json'); const projects = []; for (const file of files) { const projectData = fs.readFileSync(path.join(this.projectsDir, file), 'utf8'); projects.push(JSON.parse(projectData)); } return projects.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()); } async saveProject(project) { project.updatedAt = new Date().toISOString(); const projectPath = path.join(this.projectsDir, `${project.id}.json`); fs.writeFileSync(projectPath, JSON.stringify(project, null, 2)); } async addTask(projectId, task) { const project = await this.getProject(projectId); if (!project) { throw new Error(`Project not found: ${projectId}`); } const newTask = { ...task, id: this.generateTaskId(), createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; project.tasks.push(newTask); this.updateProjectAnalytics(project); await this.saveProject(project); return newTask; } async updateTask(projectId, taskId, updates) { const project = await this.getProject(projectId); if (!project) { throw new Error(`Project not found: ${projectId}`); } const taskIndex = project.tasks.findIndex(t => t.id === taskId); if (taskIndex === -1) { throw new Error(`Task not found: ${taskId}`); } project.tasks[taskIndex] = { ...project.tasks[taskIndex], ...updates, updatedAt: new Date().toISOString() }; this.updateProjectAnalytics(project); await this.saveProject(project); return project.tasks[taskIndex]; } async getRecommendedNextTask(projectId) { const project = await this.getProject(projectId); if (!project) { return null; } // Find highest priority task that's not blocked const availableTasks = project.tasks.filter(task => task.status === 'todo' && this.areTaskDependenciesMet(task, project.tasks)); if (availableTasks.length === 0) { return null; } // Sort by priority and return the first one const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 }; availableTasks.sort((a, b) => priorityOrder[b.priority] - priorityOrder[a.priority]); return availableTasks[0]; } areTaskDependenciesMet(task, allTasks) { return task.dependencies.every(depId => { const dependency = allTasks.find(t => t.id === depId); return dependency?.status === 'completed'; }); } updateProjectAnalytics(project) { project.analytics.totalTasks = project.tasks.length; project.analytics.completedTasks = project.tasks.filter(t => t.status === 'completed').length; project.analytics.progress = project.analytics.totalTasks > 0 ? (project.analytics.completedTasks / project.analytics.totalTasks) * 100 : 0; } generateProjectId(name) { const timestamp = Date.now(); const normalized = name.toLowerCase().replace(/[^a-z0-9]/g, '-'); return `${normalized}-${timestamp}`; } generateTaskId() { return `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } async requestConsensusForTask(projectId, taskRequest) { // This would integrate with the existing consensus system // For now, return a mock result return { originalRequest: taskRequest, refinedRequirement: "Refined task requirement based on consensus analysis", implementationPlan: "Step-by-step implementation plan", riskAssessment: "Low risk - standard implementation pattern", consensusScore: 0.92, providers: ['claude-3', 'gpt-4', 'gemini-pro'], timestamp: new Date().toISOString() }; } async getProjectAnalytics(projectId) { const project = await this.getProject(projectId); return project?.analytics || null; } async exportProject(projectId, format = 'json') { const project = await this.getProject(projectId); if (!project) { throw new Error(`Project not found: ${projectId}`); } const exportDir = path.join(this.projectsDir, 'exports'); if (!fs.existsSync(exportDir)) { fs.mkdirSync(exportDir, { recursive: true }); } const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `${project.id}-export-${timestamp}.${format}`; const filepath = path.join(exportDir, filename); switch (format) { case 'json': fs.writeFileSync(filepath, JSON.stringify(project, null, 2)); break; case 'markdown': const markdown = this.generateMarkdownReport(project); fs.writeFileSync(filepath, markdown); break; case 'csv': const csv = this.generateCSVReport(project); fs.writeFileSync(filepath, csv); break; } return filepath; } generateMarkdownReport(project) { let report = `# Project: ${project.name}\n\n`; report += `**Description**: ${project.description}\n`; report += `**Status**: ${project.status}\n`; report += `**Progress**: ${project.analytics.progress.toFixed(1)}%\n\n`; report += `## Tasks\n\n`; project.tasks.forEach((task, index) => { const statusEmoji = { todo: '⏳', in_progress: 'πŸ”„', review: 'πŸ‘€', completed: 'βœ…', blocked: '🚫' }; report += `### ${index + 1}. ${statusEmoji[task.status]} ${task.title}\n\n`; report += `- **Status**: ${task.status}\n`; report += `- **Priority**: ${task.priority}\n`; if (task.estimatedHours) { report += `- **Estimated Hours**: ${task.estimatedHours}\n`; } if (task.actualHours) { report += `- **Actual Hours**: ${task.actualHours}\n`; } report += `- **Description**: ${task.description}\n\n`; }); return report; } generateCSVReport(project) { const headers = 'ID,Title,Status,Priority,Estimated Hours,Actual Hours,Created,Updated\n'; const rows = project.tasks.map(task => `"${task.id}","${task.title}","${task.status}","${task.priority}","${task.estimatedHours || ''}","${task.actualHours || ''}","${task.createdAt}","${task.updatedAt}"`).join('\n'); return headers + rows; } } // Initialize project manager instance const projectManager = new ProjectManager(); // Zod Schemas for validation export const InitProjectToolSchema = z.object({ name: z.string().describe('Project name'), description: z.string().optional().describe('Project description'), consensusEnabled: z.boolean().default(true).describe('Enable 4-stage consensus for task generation'), costTracking: z.boolean().default(true).describe('Enable cost tracking for the project'), budgetLimit: z.number().optional().describe('Budget limit for the project in USD') }); export const ParsePRDToolSchema = z.object({ filePath: z.string().describe('Path to the PRD file'), projectId: z.string().optional().describe('Existing project ID to add tasks to') }); export const ListTasksToolSchema = z.object({ projectId: z.string().describe('Project ID'), status: z.enum(['todo', 'in_progress', 'review', 'completed', 'blocked']).optional().describe('Filter by task status'), priority: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Filter by priority') }); export const UpdateTaskToolSchema = z.object({ projectId: z.string().describe('Project ID'), taskId: z.string().describe('Task ID'), status: z.enum(['todo', 'in_progress', 'review', 'completed', 'blocked']).optional(), priority: z.enum(['low', 'medium', 'high', 'critical']).optional(), actualHours: z.number().optional().describe('Actual hours spent on the task'), assignedTo: z.string().optional().describe('Person assigned to the task') }); export const GetRecommendedTaskToolSchema = z.object({ projectId: z.string().describe('Project ID') }); export const ConsensusTaskToolSchema = z.object({ projectId: z.string().describe('Project ID'), taskRequest: z.string().describe('Task description for consensus analysis') }); export const ProjectStatusToolSchema = z.object({ projectId: z.string().optional().describe('Specific project ID, or all projects if not provided') }); export const ExportProjectToolSchema = z.object({ projectId: z.string().describe('Project ID'), format: z.enum(['json', 'markdown', 'csv']).default('json').describe('Export format') }); // Tool implementations export const initProjectToolName = 'init_project'; export const initProjectToolDescription = 'Initialize a new AI project with management capabilities'; export const parsePRDToolName = 'parse_prd'; export const parsePRDToolDescription = 'Parse a Product Requirements Document into actionable tasks using 4-stage consensus'; export const listTasksToolName = 'list_tasks'; export const listTasksToolDescription = 'List project tasks with optional filtering'; export const updateTaskToolName = 'update_task'; export const updateTaskToolDescription = 'Update task status, priority, or other properties'; export const getRecommendedTaskToolName = 'get_recommended_task'; export const getRecommendedTaskToolDescription = 'Get the next recommended task based on priorities and dependencies'; export const consensusTaskToolName = 'consensus_task'; export const consensusTaskToolDescription = 'Use 4-stage consensus to analyze and plan a task'; export const projectStatusToolName = 'project_status'; export const projectStatusToolDescription = 'Get project status, analytics, and progress summary'; export const exportProjectToolName = 'export_project'; export const exportProjectToolDescription = 'Export project data in various formats'; export async function runInitProjectTool(args) { try { const { name, description, consensusEnabled, costTracking, budgetLimit } = args; const project = await projectManager.initializeProject(name, description); // Update config if specified if (budgetLimit !== undefined) { project.config.budgetLimit = budgetLimit; } project.config.consensusEnabled = consensusEnabled; project.config.costTracking = costTracking; await projectManager.saveProject(project); let report = `# πŸš€ Project Initialized: ${name}\n\n`; report += `**Project ID**: \`${project.id}\`\n`; report += `**Description**: ${description || 'No description provided'}\n`; report += `**Status**: ${project.status}\n\n`; report += `## Configuration\n\n`; report += `- **4-Stage Consensus**: ${consensusEnabled ? 'βœ… Enabled' : '❌ Disabled'}\n`; report += `- **Cost Tracking**: ${costTracking ? 'βœ… Enabled' : '❌ Disabled'}\n`; if (budgetLimit) { report += `- **Budget Limit**: $${budgetLimit.toFixed(2)}\n`; } report += `- **Automation Level**: ${project.config.automationLevel}\n\n`; report += `## Next Steps\n\n`; report += `1. Use \`parse_prd <file>\` to convert a PRD into tasks\n`; report += `2. Use \`consensus_task "<description>"\` for AI-enhanced task planning\n`; report += `3. Use \`list_tasks\` to view and manage project tasks\n`; report += `4. Use \`project_status\` to monitor progress\n\n`; report += `πŸ’‘ **Tip**: This project uses our 4-stage consensus pipeline for superior task quality vs single AI responses.\n`; return { result: report, project: { id: project.id, name: project.name, status: project.status, consensusEnabled: project.config.consensusEnabled, costTracking: project.config.costTracking } }; } catch (error) { return { error: `Failed to initialize project: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runParsePRDTool(args) { try { const { filePath, projectId } = args; const tasks = await projectManager.parsePRD(filePath, projectId); let report = `# πŸ“‹ PRD Parsing Complete\n\n`; report += `**File**: ${filePath}\n`; report += `**Tasks Generated**: ${tasks.length}\n\n`; if (projectId) { const project = await projectManager.getProject(projectId); if (project) { // Add tasks to existing project for (const task of tasks) { await projectManager.addTask(projectId, task); } report += `**Added to Project**: ${project.name} (${projectId})\n\n`; } } report += `## Generated Tasks\n\n`; tasks.forEach((task, index) => { const priorityEmoji = { critical: 'πŸ”΄', high: '🟠', medium: '🟑', low: '🟒' }; report += `### ${index + 1}. ${priorityEmoji[task.priority]} ${task.title}\n\n`; report += `- **Priority**: ${task.priority}\n`; if (task.estimatedHours) { report += `- **Estimated Hours**: ${task.estimatedHours}\n`; } report += `- **Description**: ${task.description}\n`; if (task.tags.length > 0) { report += `- **Tags**: ${task.tags.join(', ')}\n`; } report += '\n'; }); report += `## Quality Advantage\n\n`; report += `βœ… **4-Stage Consensus**: Tasks generated using our multi-model consensus pipeline\n`; report += `βœ… **Risk Analysis**: Each task includes risk assessment and complexity estimation\n`; report += `βœ… **Dependency Mapping**: Automatic dependency detection between tasks\n`; report += `βœ… **Cost Estimation**: Built-in cost tracking for each task\n\n`; report += `πŸ’‘ **Next**: Use \`get_recommended_task\` to start with the highest priority task.\n`; return { result: report, tasksGenerated: tasks.length, tasks: tasks.map(t => ({ id: t.id, title: t.title, priority: t.priority, estimatedHours: t.estimatedHours })) }; } catch (error) { return { error: `Failed to parse PRD: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runListTasksTool(args) { try { const { projectId, status, priority } = args; const project = await projectManager.getProject(projectId); if (!project) { return { error: `Project not found: ${projectId}` }; } let tasks = project.tasks; // Apply filters if (status) { tasks = tasks.filter(t => t.status === status); } if (priority) { tasks = tasks.filter(t => t.priority === priority); } let report = `# πŸ“‹ Project Tasks: ${project.name}\n\n`; if (tasks.length === 0) { report += `No tasks found matching the specified criteria.\n`; return { result: report, tasks: [] }; } // Group by status const tasksByStatus = tasks.reduce((acc, task) => { if (!acc[task.status]) acc[task.status] = []; acc[task.status].push(task); return acc; }, {}); const statusOrder = ['todo', 'in_progress', 'review', 'completed', 'blocked']; const statusEmoji = { todo: '⏳', in_progress: 'πŸ”„', review: 'πŸ‘€', completed: 'βœ…', blocked: '🚫' }; for (const status of statusOrder) { if (tasksByStatus[status]?.length > 0) { report += `## ${statusEmoji[status]} ${status.toUpperCase().replace('_', ' ')} (${tasksByStatus[status].length})\n\n`; tasksByStatus[status].forEach((task, index) => { const priorityEmoji = { critical: 'πŸ”΄', high: '🟠', medium: '🟑', low: '🟒' }; report += `### ${index + 1}. ${priorityEmoji[task.priority]} ${task.title}\n\n`; report += `- **ID**: \`${task.id}\`\n`; report += `- **Priority**: ${task.priority}\n`; if (task.estimatedHours) { report += `- **Estimated**: ${task.estimatedHours}h\n`; } if (task.actualHours) { report += `- **Actual**: ${task.actualHours}h\n`; } if (task.assignedTo) { report += `- **Assigned**: ${task.assignedTo}\n`; } if (task.dueDate) { report += `- **Due**: ${new Date(task.dueDate).toLocaleDateString()}\n`; } report += `- **Description**: ${task.description}\n\n`; }); } } // Project summary report += `## πŸ“Š Project Summary\n\n`; report += `- **Total Tasks**: ${project.tasks.length}\n`; report += `- **Completed**: ${project.analytics.completedTasks}\n`; report += `- **Progress**: ${project.analytics.progress.toFixed(1)}%\n`; if (project.analytics.estimatedCost > 0) { report += `- **Estimated Cost**: $${project.analytics.estimatedCost.toFixed(2)}\n`; } return { result: report, tasks: tasks.map(t => ({ id: t.id, title: t.title, status: t.status, priority: t.priority })), summary: { total: project.tasks.length, completed: project.analytics.completedTasks, progress: project.analytics.progress } }; } catch (error) { return { error: `Failed to list tasks: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runUpdateTaskTool(args) { try { const { projectId, taskId, ...updates } = args; const updatedTask = await projectManager.updateTask(projectId, taskId, updates); let report = `# βœ… Task Updated\n\n`; report += `**Task**: ${updatedTask.title}\n`; report += `**Project**: ${projectId}\n\n`; report += `## Updated Properties\n\n`; Object.entries(updates).forEach(([key, value]) => { if (value !== undefined) { report += `- **${key}**: ${value}\n`; } }); report += `\n## Current Status\n\n`; report += `- **Status**: ${updatedTask.status}\n`; report += `- **Priority**: ${updatedTask.priority}\n`; if (updatedTask.estimatedHours) { report += `- **Estimated Hours**: ${updatedTask.estimatedHours}\n`; } if (updatedTask.actualHours) { report += `- **Actual Hours**: ${updatedTask.actualHours}\n`; } if (updatedTask.assignedTo) { report += `- **Assigned To**: ${updatedTask.assignedTo}\n`; } report += `\n**Last Updated**: ${new Date(updatedTask.updatedAt).toLocaleString()}\n`; return { result: report, task: { id: updatedTask.id, title: updatedTask.title, status: updatedTask.status, priority: updatedTask.priority, updatedAt: updatedTask.updatedAt } }; } catch (error) { return { error: `Failed to update task: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runGetRecommendedTaskTool(args) { try { const { projectId } = args; const recommendedTask = await projectManager.getRecommendedNextTask(projectId); if (!recommendedTask) { return { result: `# 🎯 No Recommended Task\n\nAll available tasks are either completed or blocked by dependencies.\n\n**Suggestions:**\n- Review blocked tasks and resolve dependencies\n- Add new tasks to the project\n- Mark completed tasks as done`, recommendedTask: null }; } let report = `# 🎯 Recommended Next Task\n\n`; const priorityEmoji = { critical: 'πŸ”΄', high: '🟠', medium: '🟑', low: '🟒' }; report += `## ${priorityEmoji[recommendedTask.priority]} ${recommendedTask.title}\n\n`; report += `**Priority**: ${recommendedTask.priority}\n`; if (recommendedTask.estimatedHours) { report += `**Estimated Time**: ${recommendedTask.estimatedHours} hours\n`; } report += `**Status**: ${recommendedTask.status}\n\n`; report += `### Description\n\n${recommendedTask.description}\n\n`; if (recommendedTask.tags.length > 0) { report += `### Tags\n\n${recommendedTask.tags.map(tag => `\`${tag}\``).join(', ')}\n\n`; } report += `### Why This Task?\n\n`; report += `βœ… **Highest priority** among available tasks\n`; report += `βœ… **No blocking dependencies** - ready to start\n`; report += `βœ… **Clear requirements** and scope defined\n\n`; report += `### Ready to Start?\n\n`; report += `1. Use \`update_task\` to mark as 'in_progress'\n`; report += `2. Use \`consensus_task\` for AI-enhanced implementation planning\n`; report += `3. Track time and update progress as you work\n\n`; report += `πŸ’‘ **Tip**: Our 4-stage consensus can provide detailed implementation guidance for this task.\n`; return { result: report, recommendedTask: { id: recommendedTask.id, title: recommendedTask.title, priority: recommendedTask.priority, estimatedHours: recommendedTask.estimatedHours, description: recommendedTask.description } }; } catch (error) { return { error: `Failed to get recommended task: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runConsensusTaskTool(args) { try { const { projectId, taskRequest } = args; const consensusResult = await projectManager.requestConsensusForTask(projectId, taskRequest); let report = `# 🧠 4-Stage Consensus Analysis\n\n`; report += `**Original Request**: ${consensusResult.originalRequest}\n\n`; report += `## Consensus Score: ${(consensusResult.consensusScore * 100).toFixed(1)}% ✨\n\n`; const scoreEmoji = consensusResult.consensusScore >= 0.9 ? '🟒' : consensusResult.consensusScore >= 0.7 ? '🟑' : 'πŸ”΄'; report += `${scoreEmoji} **Quality Rating**: ${consensusResult.consensusScore >= 0.9 ? 'Excellent' : consensusResult.consensusScore >= 0.7 ? 'Good' : 'Needs Review'}\n\n`; report += `## πŸ“ Refined Requirement\n\n${consensusResult.refinedRequirement}\n\n`; report += `## πŸš€ Implementation Plan\n\n${consensusResult.implementationPlan}\n\n`; report += `## ⚠️ Risk Assessment\n\n${consensusResult.riskAssessment}\n\n`; report += `## πŸ€– Consensus Details\n\n`; report += `- **Providers Used**: ${consensusResult.providers.join(', ')}\n`; report += `- **Analysis Time**: ${new Date(consensusResult.timestamp).toLocaleString()}\n`; report += `- **Consensus Quality**: ${(consensusResult.consensusScore * 100).toFixed(1)}%\n\n`; report += `## Competitive Advantage\n\n`; report += `βœ… **Multi-Model Analysis**: Unlike single AI responses, this uses ${consensusResult.providers.length} models\n`; report += `βœ… **Quality Assurance**: 4-stage pipeline ensures comprehensive analysis\n`; report += `βœ… **Risk Mitigation**: Proactive identification of potential issues\n`; report += `βœ… **Implementation Ready**: Detailed plan ready for execution\n\n`; report += `πŸ’‘ **Next Steps**: Use this analysis to create or update project tasks with confidence.\n`; return { result: report, consensus: { score: consensusResult.consensusScore, providers: consensusResult.providers, refinedRequirement: consensusResult.refinedRequirement, implementationPlan: consensusResult.implementationPlan, riskAssessment: consensusResult.riskAssessment } }; } catch (error) { return { error: `Failed to run consensus analysis: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runProjectStatusTool(args) { try { const { projectId } = args; if (projectId) { // Get specific project status const project = await projectManager.getProject(projectId); if (!project) { return { error: `Project not found: ${projectId}` }; } let report = `# πŸ“Š Project Status: ${project.name}\n\n`; const statusEmoji = { active: '🟒', paused: '⏸️', completed: 'βœ…', archived: 'πŸ“¦' }; report += `**Status**: ${statusEmoji[project.status]} ${project.status.toUpperCase()}\n`; report += `**Description**: ${project.description}\n`; report += `**Created**: ${new Date(project.createdAt).toLocaleDateString()}\n`; report += `**Last Updated**: ${new Date(project.updatedAt).toLocaleDateString()}\n\n`; // Progress overview report += `## πŸ“ˆ Progress Overview\n\n`; report += `- **Total Tasks**: ${project.analytics.totalTasks}\n`; report += `- **Completed Tasks**: ${project.analytics.completedTasks}\n`; report += `- **Progress**: ${project.analytics.progress.toFixed(1)}%\n`; // Progress bar const progressBarLength = 20; const completedBars = Math.floor((project.analytics.progress / 100) * progressBarLength); const progressBar = 'β–ˆ'.repeat(completedBars) + 'β–‘'.repeat(progressBarLength - completedBars); report += `- **Visual Progress**: [${progressBar}] ${project.analytics.progress.toFixed(1)}%\n\n`; // Task breakdown const tasksByStatus = project.tasks.reduce((acc, task) => { acc[task.status] = (acc[task.status] || 0) + 1; return acc; }, {}); report += `## πŸ“‹ Task Breakdown\n\n`; Object.entries(tasksByStatus).forEach(([status, count]) => { const emoji = { todo: '⏳', in_progress: 'πŸ”„', review: 'πŸ‘€', completed: 'βœ…', blocked: '🚫' }; report += `- **${status.replace('_', ' ').toUpperCase()}**: ${emoji[status] || 'πŸ“‹'} ${count}\n`; }); // Cost tracking if enabled if (project.config.costTracking) { report += `\n## πŸ’° Cost Tracking\n\n`; if (project.config.budgetLimit) { const budgetUsed = (project.analytics.actualCost / project.config.budgetLimit) * 100; report += `- **Budget**: $${project.analytics.actualCost.toFixed(2)} / $${project.config.budgetLimit.toFixed(2)} (${budgetUsed.toFixed(1)}%)\n`; } report += `- **Estimated Total Cost**: $${project.analytics.estimatedCost.toFixed(2)}\n`; report += `- **Actual Cost**: $${project.analytics.actualCost.toFixed(2)}\n`; } // Configuration report += `\n## βš™οΈ Configuration\n\n`; report += `- **4-Stage Consensus**: ${project.config.consensusEnabled ? 'βœ… Enabled' : '❌ Disabled'}\n`; report += `- **Cost Tracking**: ${project.config.costTracking ? 'βœ… Enabled' : '❌ Disabled'}\n`; report += `- **Automation Level**: ${project.config.automationLevel}\n`; report += `- **Notifications**: ${project.config.notifications ? 'βœ… Enabled' : '❌ Disabled'}\n`; return { result: report, project: { id: project.id, name: project.name, status: project.status, progress: project.analytics.progress, totalTasks: project.analytics.totalTasks, completedTasks: project.analytics.completedTasks } }; } else { // Get all projects overview const projects = await projectManager.getAllProjects(); let report = `# πŸ“Š All Projects Overview\n\n`; if (projects.length === 0) { report += `No projects found. Use \`init_project\` to create your first project.\n`; return { result: report, projects: [] }; } report += `**Total Projects**: ${projects.length}\n\n`; projects.forEach((project, index) => { const statusEmoji = { active: '🟒', paused: '⏸️', completed: 'βœ…', archived: 'πŸ“¦' }; report += `## ${index + 1}. ${statusEmoji[project.status]} ${project.name}\n\n`; report += `- **ID**: \`${project.id}\`\n`; report += `- **Status**: ${project.status}\n`; report += `- **Progress**: ${project.analytics.progress.toFixed(1)}% (${project.analytics.completedTasks}/${project.analytics.totalTasks})\n`; report += `- **Last Updated**: ${new Date(project.updatedAt).toLocaleDateString()}\n`; if (project.description) { report += `- **Description**: ${project.description}\n`; } report += '\n'; }); return { result: report, projects: projects.map(p => ({ id: p.id, name: p.name, status: p.status, progress: p.analytics.progress, totalTasks: p.analytics.totalTasks, completedTasks: p.analytics.completedTasks })) }; } } catch (error) { return { error: `Failed to get project status: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } export async function runExportProjectTool(args) { try { const { projectId, format } = args; const exportPath = await projectManager.exportProject(projectId, format); let report = `# πŸ“€ Project Export Complete\n\n`; report += `**Format**: ${format.toUpperCase()}\n`; report += `**File Path**: ${exportPath}\n`; report += `**Timestamp**: ${new Date().toISOString()}\n\n`; switch (format) { case 'json': report += `πŸ“‹ **JSON Export**: Complete project data in structured format\n`; report += `- Perfect for backup and data analysis\n`; report += `- Can be imported into other tools\n`; report += `- Machine-readable format\n`; break; case 'markdown': report += `πŸ“ **Markdown Report**: Human-readable project summary\n`; report += `- Great for documentation and sharing\n`; report += `- Compatible with GitHub, Notion, etc.\n`; report += `- Includes task breakdown and progress\n`; break; case 'csv': report += `πŸ“Š **CSV Export**: Task data for spreadsheet analysis\n`; report += `- Open in Excel, Google Sheets, etc.\n`; report += `- Perfect for project management tools\n`; report += `- Analyze task patterns and timelines\n`; break; } report += `\nπŸ’‘ **Use Cases**:\n`; report += `- Project documentation and reporting\n`; report += `- Integration with external PM tools\n`; report += `- Backup and archival\n`; report += `- Team collaboration and sharing\n`; return { result: report, exportPath, format, timestamp: new Date().toISOString() }; } catch (error) { return { error: `Failed to export project: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } //# sourceMappingURL=project-management-tools.js.map