UNPKG

remcode

Version:

Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.

250 lines (249 loc) 8.46 kB
"use strict"; 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.StateManager = void 0; const logger_1 = require("../utils/logger"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const logger = (0, logger_1.getLogger)('StateManager'); class StateManager { constructor(repoPath = process.cwd()) { this.configPath = path.resolve(repoPath); this.filePath = path.join(this.configPath, '.remcode'); logger.debug(`StateManager initialized with path: ${this.filePath}`); } /** * Check if the .remcode file exists */ async exists() { try { return fs.existsSync(this.filePath); } catch (error) { return false; } } /** * Load the current state from the .remcode file */ async loadState() { logger.info('Loading processing state'); try { if (!fs.existsSync(this.filePath)) { logger.warn('No .remcode file found'); return null; } const content = fs.readFileSync(this.filePath, 'utf8'); const state = JSON.parse(content); logger.info('Successfully loaded state from .remcode file'); return state; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); logger.error(`Failed to load state: ${errorMsg}`); return null; } } /** * Create initial state file if it doesn't exist */ async initializeState(initialState) { logger.info('Initializing new .remcode state'); const now = new Date().toISOString(); const defaultState = { version: '1.0.0', created: now, updated: now, repository: {}, processing: { status: 'idle' }, vectorization: {}, configuration: { includeTests: false, includeComments: true, chunkStrategy: 'hybrid' }, ...initialState }; await this.saveState(defaultState); logger.info('Successfully initialized .remcode state'); return defaultState; } /** * Save state to .remcode file */ async saveState(state) { try { // Ensure the config directory exists if (!fs.existsSync(path.dirname(this.filePath))) { fs.mkdirSync(path.dirname(this.filePath), { recursive: true }); } // Update the 'updated' timestamp state.updated = new Date().toISOString(); // Write to file with pretty formatting fs.writeFileSync(this.filePath, JSON.stringify(state, null, 2), 'utf8'); logger.debug('Successfully saved state to .remcode file'); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); logger.error(`Failed to save state: ${errorMsg}`); throw new Error(`Failed to save state: ${errorMsg}`); } } /** * Update the state with new values */ async updateState(updates) { logger.info('Updating processing state'); try { // Load current state or initialize if not exists let state = await this.loadState(); if (!state) { state = await this.initializeState(); } // Deep merge updates with current state const updatedState = this.deepMerge(state, updates); // Save updated state await this.saveState(updatedState); logger.info('Successfully updated state'); return updatedState; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); logger.error(`Failed to update state: ${errorMsg}`); throw new Error(`Failed to update state: ${errorMsg}`); } } /** * Update processing status in the state */ async updateProcessingStatus(status, lastCommit) { logger.info(`Updating processing status: ${status}`); const updates = { processing: { status, lastUpdated: new Date().toISOString() } }; if (lastCommit && updates.processing) { updates.processing.lastCommit = lastCommit; } await this.updateState(updates); } /** * Update processing statistics */ async updateStatistics(stats) { logger.info('Updating processing statistics'); // Load current state to preserve required fields const currentState = await this.loadState() || await this.initializeState(); const currentStatus = currentState.processing.status; const updates = { processing: { status: currentStatus, // Keep the existing status stats, lastUpdated: new Date().toISOString() } }; await this.updateState(updates); } /** * Update vectorization info */ async updateVectorizationInfo(info) { logger.info('Updating vectorization information'); const updates = { vectorization: { ...info, lastUpdated: new Date().toISOString() } }; await this.updateState(updates); } /** * Update repository information */ async updateRepositoryInfo(info) { logger.info('Updating repository information'); const updates = { repository: info }; await this.updateState(updates); } /** * Update configuration */ async updateConfiguration(config) { logger.info('Updating configuration'); const updates = { configuration: config }; await this.updateState(updates); } /** * Helper method to deep merge objects */ deepMerge(target, source) { if (!source) return target; const output = { ...target }; if (this.isObject(target) && this.isObject(source)) { Object.keys(source).forEach(key => { const sourceValue = source[key]; const k = key; if (this.isObject(sourceValue)) { if (!(key in target)) { output[k] = sourceValue; } else { output[k] = this.deepMerge(target[k], sourceValue); } } else { output[k] = sourceValue; } }); } return output; } /** * Helper method to check if value is an object */ isObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } } exports.StateManager = StateManager;