remcode
Version:
Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.
373 lines (372 loc) • 14 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.Prerequisites = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const child_process = __importStar(require("child_process"));
const util = __importStar(require("util"));
const logger_1 = require("../utils/logger");
const logger = (0, logger_1.getLogger)('Prerequisites');
const execAsync = util.promisify(child_process.exec);
/**
* Class to check prerequisites for remcode setup
*/
class Prerequisites {
/**
* Constructor
* @param repoPath Path to the repository
*/
constructor(repoPath = process.cwd()) {
this.repoPath = repoPath;
}
/**
* Check all prerequisites
* @returns Array of prerequisite check results
*/
async checkAll() {
logger.info('Checking prerequisites for remcode setup');
try {
// Execute all checks in parallel
const checks = [
this.checkGitRepository(),
this.checkGitHubRepository(),
this.checkNodeVersion(),
this.checkEnvironmentVariables(),
this.checkCleanWorkingDirectory(),
this.checkWritePermissions()
];
const results = await Promise.all(checks);
// Log results
const passed = results.filter(check => check.passed).length;
const failed = results.length - passed;
const criticalFailed = results.filter(check => !check.passed && check.critical).length;
logger.info(`Prerequisites check complete: ${passed}/${results.length} passed, ${failed} failed (${criticalFailed} critical)`);
return results;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error checking prerequisites: ${errorMessage}`);
// Return a generic failure if something went wrong
return [{
passed: false,
name: 'prerequisites',
message: `Error checking prerequisites: ${errorMessage}`,
critical: true
}];
}
}
/**
* Check if Git repository exists
*/
async checkGitRepository() {
const name = 'git-repository';
try {
// Check if .git directory exists
const gitDirExists = fs.existsSync(path.join(this.repoPath, '.git'));
if (!gitDirExists) {
return {
passed: false,
name,
message: 'Git repository not found',
details: 'This directory is not a Git repository. Please initialize Git with `git init` first.',
critical: true
};
}
// Verify git command is available
try {
await execAsync('git --version', { cwd: this.repoPath });
}
catch (error) {
return {
passed: false,
name,
message: 'Git command not available',
details: 'Git is not installed or not in PATH. Please install Git.',
critical: true
};
}
return {
passed: true,
name,
message: 'Git repository found',
critical: true
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking Git repository: ${errorMessage}`,
critical: true
};
}
}
/**
* Check if GitHub remote exists
*/
async checkGitHubRepository() {
const name = 'github-remote';
try {
// Check if git remote with GitHub URL exists
try {
const { stdout: remoteOutput } = await execAsync('git remote -v', { cwd: this.repoPath });
if (!remoteOutput) {
return {
passed: false,
name,
message: 'No Git remotes found',
details: 'Add a GitHub remote with `git remote add origin https://github.com/username/repo.git`',
critical: true
};
}
if (!remoteOutput.includes('github.com')) {
return {
passed: false,
name,
message: 'No GitHub remote found',
details: 'Add a GitHub remote with `git remote add origin https://github.com/username/repo.git`',
critical: true
};
}
return {
passed: true,
name,
message: 'GitHub repository configured',
critical: true
};
}
catch (error) {
return {
passed: false,
name,
message: 'Failed to check Git remotes',
details: 'Ensure Git is properly installed and initialized',
critical: true
};
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking GitHub repository: ${errorMessage}`,
critical: true
};
}
}
/**
* Check if Node.js version is compatible
*/
async checkNodeVersion() {
const name = 'node-version';
const minVersion = 14; // Minimum Node.js version required
try {
const nodeVersion = process.version;
const versionNumber = parseInt(nodeVersion.substring(1).split('.')[0], 10);
if (versionNumber < minVersion) {
return {
passed: false,
name,
message: `Node.js version ${nodeVersion} is not supported`,
details: `Please upgrade to Node.js v${minVersion} or higher`,
critical: true
};
}
return {
passed: true,
name,
message: `Node.js version ${nodeVersion} is compatible`,
critical: true
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking Node.js version: ${errorMessage}`,
critical: true
};
}
}
/**
* Check if required environment variables are set
*/
checkEnvironmentVariables() {
const name = 'environment-variables';
try {
// Check for required environment variables
const requiredVars = ['GITHUB_TOKEN']; // Add any other required variables
const missingVars = requiredVars.filter(varName => !process.env[varName]);
// Optional but recommended variables
const recommendedVars = ['PINECONE_API_KEY', 'HUGGINGFACE_TOKEN'];
const missingRecommended = recommendedVars.filter(varName => !process.env[varName]);
if (missingVars.length > 0) {
return {
passed: false,
name,
message: `Missing required environment variables: ${missingVars.join(', ')}`,
details: 'These variables are needed for Remcode to function properly',
critical: true
};
}
if (missingRecommended.length > 0) {
return {
passed: true, // Still pass, but with a warning
name,
message: `Required environment variables found, but missing recommended: ${missingRecommended.join(', ')}`,
details: 'These variables are recommended for full functionality',
critical: false
};
}
return {
passed: true,
name,
message: 'All environment variables configured',
critical: false
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking environment variables: ${errorMessage}`,
critical: true
};
}
}
/**
* Check if working directory is clean
*/
async checkCleanWorkingDirectory() {
const name = 'clean-working-directory';
try {
try {
const { stdout: statusOutput } = await execAsync('git status --porcelain', { cwd: this.repoPath });
if (statusOutput.trim()) {
return {
passed: false,
name,
message: 'Working directory has uncommitted changes',
details: 'Commit or stash your changes before continuing',
critical: false // Not critical, but recommended
};
}
return {
passed: true,
name,
message: 'Working directory is clean',
critical: false
};
}
catch (error) {
return {
passed: false,
name,
message: 'Failed to check working directory status',
details: 'Ensure Git is properly installed and initialized',
critical: false
};
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking working directory: ${errorMessage}`,
critical: false
};
}
}
/**
* Check if we have write permissions in the repository
*/
async checkWritePermissions() {
const name = 'write-permissions';
try {
// Try to create and remove a test file
const testFilePath = path.join(this.repoPath, '.remcode-test');
try {
// Write test file
fs.writeFileSync(testFilePath, 'test');
// Check if file was created
const fileExists = fs.existsSync(testFilePath);
// Clean up
if (fileExists) {
fs.unlinkSync(testFilePath);
}
if (!fileExists) {
return {
passed: false,
name,
message: 'No write permissions in repository',
details: 'Ensure you have write permissions to this directory',
critical: true
};
}
return {
passed: true,
name,
message: 'Write permissions verified',
critical: true
};
}
catch (error) {
return {
passed: false,
name,
message: 'No write permissions in repository',
details: `Failed to create test file: ${error instanceof Error ? error.message : String(error)}`,
critical: true
};
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
passed: false,
name,
message: `Error checking write permissions: ${errorMessage}`,
critical: true
};
}
}
}
exports.Prerequisites = Prerequisites;
;