mcp-booster
Version:
Servidor MCP com CoConuT (Continuous Chain of Thought) para uso com Cursor IDE - Pacote Global NPM
379 lines (378 loc) • 14.3 kB
JavaScript
"use strict";
/**
* Sistema de persistência para histórico de pensamentos
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.StorageFactory = exports.MemoryStorageProvider = exports.FileStorageProvider = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const logger_1 = require("./logger");
/**
* Implementação de armazenamento em arquivo
*/
class FileStorageProvider {
constructor(config) {
this.filePath = null;
this.branchesFilePath = null;
this.config = config;
this.logger = logger_1.Logger.getInstance();
// Não inicializar os caminhos no construtor, eles serão definidos quando necessário
}
/**
* Configura os caminhos de arquivo com base no projectPath fornecido
*/
setupPaths(projectPath) {
// Criar diretório de dados no caminho especificado
const storageDir = path.resolve(projectPath, 'booster-data');
this.filePath = path.resolve(storageDir, 'thought-history.json');
this.branchesFilePath = path.resolve(storageDir, 'branches.json');
// Garantir que o diretório existe
if (!fs.existsSync(storageDir)) {
try {
fs.mkdirSync(storageDir, { recursive: true });
this.logger.info('Diretório de armazenamento criado', { storageDir });
}
catch (error) {
this.logger.error('Falha ao criar diretório de armazenamento', { error, storageDir });
throw new Error(`Falha ao criar diretório de armazenamento: ${error?.message || 'Erro desconhecido'}`);
}
}
this.logger.debug('Diretório de armazenamento configurado', {
storageDir,
filePath: this.filePath,
branchesFilePath: this.branchesFilePath
});
}
/**
* Inicializa o provedor de armazenamento
*/
async initialize() {
// Não fazer nada no initialize, pois os caminhos serão configurados quando necessário
this.logger.debug('FileStorageProvider inicializado');
}
/**
* Salva um pensamento no armazenamento
* @param entry Entrada de pensamento a ser salva
* @param projectPath Caminho opcional do projeto para salvar (sobrescreve config.projectPath)
* @returns Informações sobre o arquivo salvo
*/
async saveThought(entry, projectPath) {
try {
// Usar o projectPath fornecido ou o da configuração
const effectiveProjectPath = projectPath || this.config.projectPath;
if (!effectiveProjectPath) {
throw new Error("Nenhum caminho foi fornecido para salvar os arquivos");
}
// Configurar caminhos se necessário
if (!this.filePath) {
this.setupPaths(effectiveProjectPath);
}
if (!this.filePath) {
throw new Error("Falha ao configurar caminhos de armazenamento");
}
// Carregar histórico existente
const history = await this.loadHistory();
// Verificar se é uma revisão
const index = history.findIndex(t => t.thoughtNumber === entry.thoughtNumber && t.branchId === entry.branchId);
if (index >= 0) {
// Atualizar pensamento existente
history[index] = entry;
}
else {
// Adicionar novo pensamento
history.push(entry);
}
// Salvar histórico atualizado
await fs.promises.writeFile(this.filePath, JSON.stringify(history, null, 2));
this.logger.debug('Pensamento salvo com sucesso', { entry });
// Retornar informações sobre o arquivo salvo
return {
filePath: this.filePath,
type: 'thought',
timestamp: Date.now()
};
}
catch (error) {
this.logger.error('Erro ao salvar pensamento', { error, entry });
throw new Error(`Falha ao salvar pensamento: ${error?.message || 'Erro desconhecido'}`);
}
}
/**
* Carrega o histórico completo de pensamentos
*/
async loadHistory() {
try {
if (!this.filePath) {
throw new Error("Caminho do arquivo de histórico não configurado");
}
const data = await fs.promises.readFile(this.filePath, 'utf-8');
const history = JSON.parse(data);
this.logger.debug('Histórico carregado com sucesso', { count: history.length });
return history;
}
catch (error) {
this.logger.error('Erro ao carregar histórico', { error });
return [];
}
}
/**
* Salva informações sobre uma ramificação específica
* @returns Informações sobre o arquivo salvo
*/
async saveBranch(branchId, thoughtNumbers) {
try {
// Carregar branches existentes
const branches = await this.loadBranches();
// Atualizar ou adicionar a branch específica
branches[branchId] = thoughtNumbers;
// Salvar branches atualizadas
const branchesFilePath = this.branchesFilePath || path.resolve(this.config.projectPath || '', 'branches.json');
await fs.promises.writeFile(branchesFilePath, JSON.stringify(branches, null, 2));
this.logger.debug('Ramificação salva com sucesso', { branchId, thoughtNumbers });
// Retornar informações sobre o arquivo salvo
return {
filePath: branchesFilePath,
type: 'branch',
timestamp: Date.now()
};
}
catch (error) {
this.logger.error('Erro ao salvar ramificação', { error, branchId });
throw new Error(`Falha ao salvar ramificação: ${error?.message || 'Erro desconhecido'}`);
}
}
/**
* Carrega informações sobre ramificações
*/
async loadBranches() {
try {
if (!this.branchesFilePath) {
throw new Error("Caminho do arquivo de branches não configurado");
}
const data = await fs.promises.readFile(this.branchesFilePath, 'utf-8');
const branches = JSON.parse(data);
this.logger.debug('Ramificações carregadas com sucesso', { branches });
return branches;
}
catch (error) {
this.logger.error('Erro ao carregar ramificações', { error });
return { 'main': [] };
}
}
/**
* Limpa todo o armazenamento
*/
async clear() {
try {
if (this.filePath && fs.existsSync(this.filePath)) {
await fs.promises.unlink(this.filePath);
}
if (this.branchesFilePath && fs.existsSync(this.branchesFilePath)) {
await fs.promises.unlink(this.branchesFilePath);
}
this.logger.info('Armazenamento limpo com sucesso');
}
catch (error) {
this.logger.error('Erro ao limpar armazenamento', { error });
throw new Error(`Falha ao limpar armazenamento: ${error?.message || 'Erro desconhecido'}`);
}
}
/**
* Exporta todos os dados armazenados
*/
async exportData() {
const thoughts = await this.loadHistory();
const branches = await this.loadBranches();
return {
thoughts,
branches
};
}
/**
* Importa dados para o armazenamento
*/
async importData(data) {
try {
// Garantir que os diretórios existam
const storageDir = path.dirname(this.filePath || '');
if (!fs.existsSync(storageDir)) {
fs.mkdirSync(storageDir, { recursive: true });
}
// Salvar pensamentos
await fs.promises.writeFile(this.filePath || '', JSON.stringify(data.thoughts, null, 2));
// Salvar branches
await fs.promises.writeFile(this.branchesFilePath || '', JSON.stringify(data.branches, null, 2));
this.logger.info('Dados importados com sucesso', {
thoughtCount: data.thoughts.length,
branchCount: Object.keys(data.branches).length
});
}
catch (error) {
this.logger.error('Erro ao importar dados', { error });
throw new Error(`Falha ao importar dados: ${error?.message || 'Erro desconhecido'}`);
}
}
}
exports.FileStorageProvider = FileStorageProvider;
/**
* Implementação de armazenamento em memória
*/
class MemoryStorageProvider {
constructor() {
this.thoughts = [];
this.branches = { 'main': [] };
this.logger = logger_1.Logger.getInstance();
}
/**
* Inicializa o provedor de armazenamento
*/
async initialize() {
this.logger.debug('MemoryStorageProvider inicializado');
}
/**
* Guarda um pensamento em memória
* @returns Informações sobre o pensamento guardado
*/
async saveThought(entry) {
try {
// Verificar se é uma revisão
const index = this.thoughts.findIndex(t => t.thoughtNumber === entry.thoughtNumber && t.branchId === entry.branchId);
if (index >= 0) {
// Atualizar pensamento existente
this.thoughts[index] = entry;
}
else {
// Adicionar novo pensamento
this.thoughts.push(entry);
}
this.logger.debug('Pensamento guardado em memória', { entry });
// Retornar informações sobre o pensamento guardado
return {
filePath: 'memory://thought',
type: 'thought',
timestamp: Date.now()
};
}
catch (error) {
this.logger.error('Erro ao guardar pensamento em memória', { error, entry });
return null;
}
}
/**
* Carrega o histórico completo de pensamentos da memória
*/
async loadHistory() {
return [...this.thoughts];
}
/**
* Guarda informações sobre uma ramificação específica
* @returns Informações sobre a ramificação guardada
*/
async saveBranch(branchId, thoughtNumbers) {
try {
// Atualizar ou adicionar a branch específica
this.branches[branchId] = thoughtNumbers;
this.logger.debug('Ramificação guardada em memória', { branchId, thoughtNumbers });
// Retornar informações sobre a ramificação guardada
return {
filePath: 'memory://branch',
type: 'branch',
timestamp: Date.now()
};
}
catch (error) {
this.logger.error('Erro ao guardar ramificação em memória', { error, branchId });
return null;
}
}
/**
* Carrega informações sobre ramificações da memória
*/
async loadBranches() {
return { ...this.branches };
}
/**
* Limpa toda a memória
*/
async clear() {
this.thoughts = [];
this.branches = { 'main': [] };
this.logger.debug('Memória limpa');
}
/**
* Exporta todos os dados da memória
*/
async exportData() {
return {
thoughts: [...this.thoughts],
branches: { ...this.branches }
};
}
/**
* Importa dados para a memória
*/
async importData(data) {
this.thoughts = [...data.thoughts];
this.branches = { ...data.branches };
this.logger.debug('Dados importados para a memória', {
thoughtCount: this.thoughts.length,
branchCount: Object.keys(this.branches).length
});
}
}
exports.MemoryStorageProvider = MemoryStorageProvider;
/**
* Fábrica para criar provedores de armazenamento
*/
class StorageFactory {
static createProvider(config) {
// Verificar se estamos usando persistência
if (config.persistenceEnabled) {
// Quando persistência está habilitada, verificar se temos um caminho de projeto
if (!config.projectPath) {
// Se não houver caminho disponível, lançar erro
throw new Error("Nenhum caminho foi fornecido para salvar os arquivos");
}
// Se temos um caminho válido, usar o FileStorageProvider
return new FileStorageProvider(config);
}
else {
// Se persistência não estiver habilitada, usar armazenamento em memória
return new MemoryStorageProvider();
}
}
}
exports.StorageFactory = StorageFactory;