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