@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
JavaScript
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