@andrebuzeli/advanced-memory-markdown-mcp
Version:
Advanced Memory Bank MCP v3.1.5 - Sistema avançado de gerenciamento de memória com isolamento de projetos por IDE, sincronização sob demanda, backup a cada 30min, apenas arquivos .md principais sincronizados, pasta reasoning temporária com limpeza automát
291 lines • 11.3 kB
JavaScript
/**
* Plan Manager v2.0 - Gerencia planejamentos estratégicos em arquivos markdown
*
* IMPORTANTE - NOME DO PROJETO:
* - O projectName DEVE ser exatamente o nome da pasta RAIZ do projeto aberto no IDE
* - NÃO é uma subpasta, NÃO é um subprojeto - é a pasta raiz que foi aberta no IDE
* - O nome deve ser uma cópia EXATA sem adicionar ou remover nada
*
* RESPONSABILIDADE - PLANEJAMENTO ESTRATÉGICO:
* - Roadmaps de projeto e releases
* - Planejamento de sprints e milestones
* - Objetivos estratégicos e metas
* - Cronogramas e deadlines
* - Planejamento de recursos e capacidade
* - Visão de alto nível do projeto
*
* Funcionalidades v2.0:
* - Operações individuais e múltiplas em planos
* - Criação e gerenciamento de planos estratégicos
* - Sistema de prioridades e status temporal
* - Armazenamento em plan.md no MEMORY_BANK_ROOT
* - Tags e categorização por objetivos
* - Sincronização automática com pasta .memory-bank local
*/
import * as fs from 'fs/promises';
import { SyncManager } from './sync-manager.js';
export class PlanManager {
syncManager;
constructor() {
this.syncManager = new SyncManager();
}
/**
* Creates a new plan
*/
async create(projectName, name, description, priority = 5, tags = []) {
// Ensure project structure exists
await this.syncManager.ensureProjectStructure(projectName);
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plan = {
id: this.generatePlanId(),
name,
description,
priority: Math.max(1, Math.min(10, priority)),
status: 'pending',
tags,
created: Date.now(),
modified: Date.now()
};
await this.addPlanToFile(planFile, plan);
return plan;
}
/**
* Reads a specific plan
*/
async read(projectName, planId) {
const plans = await this.list(projectName);
return plans.find(plan => plan.id === planId) || null;
}
/**
* Updates a plan
*/
async update(projectName, planId, updates) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plans = await this.loadPlansFromFile(planFile);
const planIndex = plans.findIndex(plan => plan.id === planId);
if (planIndex === -1)
return null;
const updatedPlan = {
...plans[planIndex],
...updates,
modified: Date.now()
};
plans[planIndex] = updatedPlan;
await this.savePlansToFile(planFile, plans);
return updatedPlan;
}
/**
* Deletes a plan
*/
async delete(projectName, planId) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plans = await this.loadPlansFromFile(planFile);
const filteredPlans = plans.filter(plan => plan.id !== planId);
if (filteredPlans.length === plans.length)
return false;
await this.savePlansToFile(planFile, filteredPlans);
return true;
}
/**
* Lists all plans for a project
*/
async list(projectName) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
return await this.loadPlansFromFile(planFile);
}
// ========== OPERAÇÕES MÚLTIPLAS v2.0 ==========
/**
* Creates multiple plans at once
*/
async createMultiple(projectName, plans) {
await this.syncManager.ensureProjectStructure(projectName);
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const existingPlans = await this.loadPlansFromFile(planFile);
const createdPlans = [];
for (const planData of plans) {
const plan = {
id: this.generatePlanId(),
name: planData.name,
description: planData.description,
created: Date.now(),
modified: Date.now(),
status: 'pending',
priority: planData.priority || 5,
tags: planData.tags || []
};
existingPlans.push(plan);
createdPlans.push(plan);
}
await this.savePlansToFile(planFile, existingPlans);
return createdPlans;
}
/**
* Reads multiple plans at once
*/
async readMultiple(projectName, planIds) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plans = await this.loadPlansFromFile(planFile);
return planIds.map(planId => plans.find(plan => plan.id === planId) || null);
}
/**
* Updates multiple plans at once
*/
async updateMultiple(projectName, updates) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plans = await this.loadPlansFromFile(planFile);
const updatedPlans = [];
for (const updateData of updates) {
const planIndex = plans.findIndex(plan => plan.id === updateData.planId);
if (planIndex !== -1) {
const updatedPlan = {
...plans[planIndex],
...updateData.updates,
modified: Date.now()
};
plans[planIndex] = updatedPlan;
updatedPlans.push(updatedPlan);
}
else {
updatedPlans.push(null);
}
}
await this.savePlansToFile(planFile, plans);
return updatedPlans;
}
/**
* Deletes multiple plans at once
*/
async deleteMultiple(projectName, planIds) {
const planFile = this.syncManager.getProjectFilePath(projectName, 'plan.md');
const plans = await this.loadPlansFromFile(planFile);
const results = [];
for (const planId of planIds) {
const initialLength = plans.length;
const filteredPlans = plans.filter(plan => plan.id !== planId);
if (filteredPlans.length < initialLength) {
results.push(true);
// Update the plans array for next iteration
plans.splice(0, plans.length, ...filteredPlans);
}
else {
results.push(false);
}
}
await this.savePlansToFile(planFile, plans);
return results;
}
/**
* Generates a unique plan ID
*/
generatePlanId() {
return `PLAN-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
/**
* Adds a plan to the planning.md file
*/
async addPlanToFile(filePath, plan) {
const plans = await this.loadPlansFromFile(filePath);
plans.push(plan);
await this.savePlansToFile(filePath, plans);
}
/**
* Loads plans from planning.md file
*/
async loadPlansFromFile(filePath) {
try {
const content = await fs.readFile(filePath, 'utf8');
const plans = [];
// Parse markdown content to extract plans
const lines = content.split('\n');
let currentPlan = null;
let inPlanSection = false;
for (const line of lines) {
if (line.startsWith('## Planos') || line.startsWith('## Planejamentos')) {
inPlanSection = true;
continue;
}
if (inPlanSection && line.startsWith('---')) {
break;
}
if (inPlanSection && line.startsWith('### ')) {
// Save previous plan if exists
if (currentPlan && currentPlan.id) {
plans.push(currentPlan);
}
// Start new plan
const planMatch = line.match(/### (.+) \(ID: (.+)\)/);
if (planMatch && planMatch[1] && planMatch[2]) {
currentPlan = {
id: planMatch[2],
name: planMatch[1]
};
}
}
if (currentPlan && inPlanSection) {
if (line.startsWith('**Descrição:**')) {
currentPlan.description = line.replace('**Descrição:**', '').trim();
}
else if (line.startsWith('**Status:**')) {
currentPlan.status = line.replace('**Status:**', '').trim();
}
else if (line.startsWith('**Prioridade:**')) {
currentPlan.priority = parseInt(line.replace('**Prioridade:**', '').trim());
}
else if (line.startsWith('**Tags:**')) {
const tagsStr = line.replace('**Tags:**', '').trim();
currentPlan.tags = tagsStr ? tagsStr.split(', ') : [];
}
else if (line.startsWith('**Criado:**')) {
currentPlan.created = parseInt(line.replace('**Criado:**', '').trim());
}
else if (line.startsWith('**Modificado:**')) {
currentPlan.modified = parseInt(line.replace('**Modificado:**', '').trim());
}
}
}
// Save last plan if exists
if (currentPlan && currentPlan.id) {
plans.push(currentPlan);
}
return plans;
}
catch {
return [];
}
}
/**
* Saves plans to planning.md file
*/
async savePlansToFile(filePath, plans) {
try {
const content = await fs.readFile(filePath, 'utf8');
const lines = content.split('\n');
// Find the plans section
const plansIndex = lines.findIndex(line => line.startsWith('## Planos') || line.startsWith('## Planejamentos'));
const endIndex = lines.findIndex((line, index) => index > plansIndex && line.startsWith('---'));
if (plansIndex === -1)
return;
// Build new plans section
const newPlansSection = ['## Planos', ''];
if (plans.length === 0) {
newPlansSection.push('<!-- Nenhum plano criado ainda -->', '');
}
else {
for (const plan of plans) {
newPlansSection.push(`### ${plan.name} (ID: ${plan.id})`, `**Descrição:** ${plan.description}`, `**Status:** ${plan.status}`, `**Prioridade:** ${plan.priority}`, `**Tags:** ${plan.tags.join(', ')}`, `**Criado:** ${plan.created}`, `**Modificado:** ${plan.modified}`, '');
}
}
// Replace the plans section
const newLines = [
...lines.slice(0, plansIndex),
...newPlansSection,
...lines.slice(endIndex)
];
await fs.writeFile(filePath, newLines.join('\n'), 'utf8');
}
catch (error) {
console.error('Error saving plans to file:', error);
}
}
}
//# sourceMappingURL=plan-manager.js.map