UNPKG

@mickdarling/dollhousemcp

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

134 lines 17.9 kB
/** * Version management and comparison utilities */ import * as fs from 'fs/promises'; import * as path from 'path'; export class VersionManager { /** * Get current version from package.json */ async getCurrentVersion() { // Use process.cwd() as a base, then search upward for package.json let currentDir = process.cwd(); let packageJsonPath = null; // Search up to 5 levels for package.json for (let i = 0; i < 5; i++) { const candidatePath = path.join(currentDir, 'package.json'); try { await fs.access(candidatePath); packageJsonPath = candidatePath; break; } catch { // File doesn't exist, try parent directory const parentDir = path.dirname(currentDir); if (parentDir === currentDir) { // We've reached the root break; } currentDir = parentDir; } } if (!packageJsonPath) { throw new Error('Could not find package.json in current directory or any parent directory'); } const packageContent = await fs.readFile(packageJsonPath, 'utf-8'); const packageData = JSON.parse(packageContent); return packageData.version; } /** * Enhanced semantic version comparison supporting pre-release versions * Returns: -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2 */ compareVersions(version1, version2) { // Normalize versions by removing 'v' prefix const v1 = version1.replace(/^v/, ''); const v2 = version2.replace(/^v/, ''); // Split version and pre-release parts const [v1main, v1pre] = v1.split('-'); const [v2main, v2pre] = v2.split('-'); // Compare main version parts (x.y.z) const v1parts = v1main.split('.').map(part => parseInt(part) || 0); const v2parts = v2main.split('.').map(part => parseInt(part) || 0); const maxLength = Math.max(v1parts.length, v2parts.length); for (let i = 0; i < maxLength; i++) { const v1part = v1parts[i] || 0; const v2part = v2parts[i] || 0; if (v1part < v2part) return -1; if (v1part > v2part) return 1; } // If main versions are equal, compare pre-release versions // Version without pre-release is greater than version with pre-release if (!v1pre && v2pre) return 1; // 1.0.0 > 1.0.0-beta if (v1pre && !v2pre) return -1; // 1.0.0-beta < 1.0.0 if (!v1pre && !v2pre) return 0; // 1.0.0 == 1.0.0 // Both have pre-release, compare lexicographically return v1pre.localeCompare(v2pre); } /** * Parse version from dependency output */ parseVersionFromOutput(output, tool) { // Git version output: "git version 2.39.2" // npm version output: "8.19.2" or JSON with version info if (tool === 'git') { const match = output.match(/git version (\d+\.\d+\.\d+)/); return match ? match[1] : null; } else if (tool === 'npm') { // npm might return just the version number or JSON const cleanOutput = output.trim(); if (cleanOutput.match(/^\d+\.\d+\.\d+/)) { return cleanOutput.split('\n')[0]; // First line if multiple lines } // Try to parse as JSON if it looks like JSON try { const parsed = JSON.parse(cleanOutput); return parsed.npm || parsed.version || null; } catch { // If not JSON, try to extract version pattern const match = cleanOutput.match(/(\d+\.\d+\.\d+)/); return match ? match[1] : null; } } return null; } /** * Validate that a dependency version meets requirements */ validateDependencyVersion(actualVersion, requirements, toolName) { const minComparison = this.compareVersions(actualVersion, requirements.minimum); const maxComparison = this.compareVersions(actualVersion, requirements.maximum); // Check if version is below minimum if (minComparison < 0) { return { valid: false, error: `${toolName} version ${actualVersion} is below minimum required version ${requirements.minimum}. Please upgrade ${toolName}.` }; } // Check if version is above maximum tested if (maxComparison > 0) { return { valid: true, warning: `${toolName} version ${actualVersion} is above maximum tested version ${requirements.maximum}. Some features may not work as expected.` }; } // Check if not at recommended version const recComparison = this.compareVersions(actualVersion, requirements.recommended); if (recComparison !== 0) { return { valid: true, warning: `${toolName} version ${actualVersion} works but ${requirements.recommended} is recommended for optimal stability.` }; } // Version is perfect return { valid: true }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmVyc2lvbk1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXBkYXRlL1ZlcnNpb25NYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFFN0IsTUFBTSxPQUFPLGNBQWM7SUFDekI7O09BRUc7SUFDSCxLQUFLLENBQUMsaUJBQWlCO1FBQ3JCLG1FQUFtRTtRQUNuRSxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDL0IsSUFBSSxlQUFlLEdBQWtCLElBQUksQ0FBQztRQUUxQyx5Q0FBeUM7UUFDekMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQztnQkFDSCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQy9CLGVBQWUsR0FBRyxhQUFhLENBQUM7Z0JBQ2hDLE1BQU07WUFDUixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLDJDQUEyQztnQkFDM0MsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxTQUFTLEtBQUssVUFBVSxFQUFFLENBQUM7b0JBQzdCLHlCQUF5QjtvQkFDekIsTUFBTTtnQkFDUixDQUFDO2dCQUNELFVBQVUsR0FBRyxTQUFTLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQywwRUFBMEUsQ0FBQyxD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O2FBQ3JJLENBQUM7UUFDSixDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLElBQUksYUFBYSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsT0FBTyxFQUFFLEdBQUcsUUFBUSxZQUFZLGFBQWEsb0NBQW9DLFlBQVksQ0FBQyxPQUFPLDJDQUEyQzthQUNqSixDQUFDO1FBQ0osQ0FBQztRQUVELHNDQUFzQztRQUN0QyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDcEYsSUFBSSxhQUFhLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsT0FBTztnQkFDTCxLQUFLLEVBQUUsSUFBSTtnQkFDWCxPQUFPLEVBQUUsR0FBRyxRQUFRLFlBQVksYUFBYSxjQUFjLFlBQVksQ0FBQyxXQUFXLHdDQUF3QzthQUM1SCxDQUFDO1FBQ0osQ0FBQztRQUVELHFCQUFxQjtRQUNyQixPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ3pCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVmVyc2lvbiBtYW5hZ2VtZW50IGFuZCBjb21wYXJpc29uIHV0aWxpdGllc1xuICovXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzL3Byb21pc2VzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5cbmV4cG9ydCBjbGFzcyBWZXJzaW9uTWFuYWdlciB7XG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCB2ZXJzaW9uIGZyb20gcGFja2FnZS5qc29uXG4gICAqL1xuICBhc3luYyBnZXRDdXJyZW50VmVyc2lvbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIC8vIFVzZSBwcm9jZXNzLmN3ZCgpIGFzIGEgYmFzZSwgdGhlbiBzZWFyY2ggdXB3YXJkIGZvciBwYWNrYWdlLmpzb25cbiAgICBsZXQgY3VycmVudERpciA9IHByb2Nlc3MuY3dkKCk7XG4gICAgbGV0IHBhY2thZ2VKc29uUGF0aDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgXG4gICAgLy8gU2VhcmNoIHVwIHRvIDUgbGV2ZWxzIGZvciBwYWNrYWdlLmpzb25cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgICAgY29uc3QgY2FuZGlkYXRlUGF0aCA9IHBhdGguam9pbihjdXJyZW50RGlyLCAncGFja2FnZS5qc29uJyk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoY2FuZGlkYXRlUGF0aCk7XG4gICAgICAgIHBhY2thZ2VKc29uUGF0aCA9IGNhbmRpZGF0ZVBhdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIEZpbGUgZG9lc24ndCBleGlzdCwgdHJ5IHBhcmVudCBkaXJlY3RvcnlcbiAgICAgICAgY29uc3QgcGFyZW50RGlyID0gcGF0aC5kaXJuYW1lKGN1cnJlbnREaXIpO1xuICAgICAgICBpZiAocGFyZW50RGlyID09PSBjdXJyZW50RGlyKSB7XG4gICAgICAgICAgLy8gV2UndmUgcmVhY2hlZCB0aGUgcm9vdFxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnREaXIgPSBwYXJlbnREaXI7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIGlmICghcGFja2FnZUpzb25QYXRoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBmaW5kIHBhY2thZ2UuanNvbiBpbiBjdXJyZW50IGRpcmVjdG9yeSBvciBhbnkgcGFyZW50IGRpcmVjdG9yeScpO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBwYWNrYWdlQ29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKHBhY2thZ2VKc29uUGF0aCwgJ3V0Zi04Jyk7XG4gICAgY29uc3QgcGFja2FnZURhdGEgPSBKU09OLnBhcnNlKHBhY2thZ2VDb250ZW50KTtcbiAgICByZXR1cm4gcGFja2FnZURhdGEudmVyc2lvbjtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEVuaGFuY2VkIHNlbWFudGljIHZlcnNpb24gY29tcGFyaXNvbiBzdXBwb3J0aW5nIHByZS1yZWxlYXNlIHZlcnNpb25zXG4gICAqIFJldHVybnM6IC0xIGlmIHYxIDwgdjIsIDAgaWYgdjEgPT0gdjIsIDEgaWYgdjEgPiB2MlxuICAgKi9cbiAgY29tcGFyZVZlcnNpb25zKHZlcnNpb24xOiBzdHJpbmcsIHZlcnNpb24yOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIC8vIE5vcm1hbGl6ZSB2ZXJzaW9ucyBieSByZW1vdmluZyAndicgcHJlZml4XG4gICAgY29uc3QgdjEgPSB2ZXJzaW9uMS5yZXBsYWNlKC9edi8sICcnKTtcbiAgICBjb25zdCB2MiA9IHZlcnNpb24yLnJlcGxhY2UoL152LywgJycpO1xuICAgIFxuICAgIC8vIFNwbGl0IHZlcnNpb24gYW5kIHByZS1yZWxlYXNlIHBhcnRzXG4gICAgY29uc3QgW3YxbWFpbiwgdjFwcmVdID0gdjEuc3BsaXQoJy0nKTtcbiAgICBjb25zdCBbdjJtYWluLCB2MnByZV0gPSB2Mi5zcGxpdCgnLScpO1xuICAgIFxuICAgIC8vIENvbXBhcmUgbWFpbiB2ZXJzaW9uIHBhcnRzICh4LnkueilcbiAgICBjb25zdCB2MXBhcnRzID0gdjFtYWluLnNwbGl0KCcuJykubWFwKHBhcnQgPT4gcGFyc2VJbnQocGFydCkgfHwgMCk7XG4gICAgY29uc3QgdjJwYXJ0cyA9IHYybWFpbi5zcGxpdCgnLicpLm1hcChwYXJ0ID0+IHBhcnNlSW50KHBhcnQpIHx8IDApO1xuICAgIFxuICAgIGNvbnN0IG1heExlbmd0aCA9IE1hdGgubWF4KHYxcGFydHMubGVuZ3RoLCB2MnBhcnRzLmxlbmd0aCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhMZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdjFwYXJ0ID0gdjFwYXJ0c1tpXSB8fCAwO1xuICAgICAgY29uc3QgdjJwYXJ0ID0gdjJwYXJ0c1tpXSB8fCAwO1xuICAgICAgXG4gICAgICBpZiAodjFwYXJ0IDwgdjJwYXJ0KSByZXR1cm4gLTE7XG4gICAgICBpZiAodjFwYXJ0ID4gdjJwYXJ0KSByZXR1cm4gMTtcbiAgICB9XG4gICAgXG4gICAgLy8gSWYgbWFpbiB2ZXJzaW9ucyBhcmUgZXF1YWwsIGNvbXBhcmUgcHJlLXJlbGVhc2UgdmVyc2lvbnNcbiAgICAvLyBWZXJzaW9uIHdpdGhvdXQgcHJlLXJlbGVhc2UgaXMgZ3JlYXRlciB0aGFuIHZlcnNpb24gd2l0aCBwcmUtcmVsZWFzZVxuICAgIGlmICghdjFwcmUgJiYgdjJwcmUpIHJldHVybiAxOyAgIC8vIDEuMC4wID4gMS4wLjAtYmV0YVxuICAgIGlmICh2MXByZSAmJiAhdjJwcmUpIHJldHVybiAtMTsgIC8vIDEuMC4wLWJldGEgPCAxLjAuMFxuICAgIGlmICghdjFwcmUgJiYgIXYycHJlKSByZXR1cm4gMDsgIC8vIDEuMC4wID09IDEuMC4wXG4gICAgXG4gICAgLy8gQm90aCBoYXZlIHByZS1yZWxlYXNlLCBjb21wYXJlIGxleGljb2dyYXBoaWNhbGx5XG4gICAgcmV0dXJuIHYxcHJlLmxvY2FsZUNvbXBhcmUodjJwcmUpO1xuICB9XG4gIFxuICAvKipcbiAgICogUGFyc2UgdmVyc2lvbiBmcm9tIGRlcGVuZGVuY3kgb3V0cHV0XG4gICAqL1xuICBwYXJzZVZlcnNpb25Gcm9tT3V0cHV0KG91dHB1dDogc3RyaW5nLCB0b29sOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAvLyBHaXQgdmVyc2lvbiBvdXRwdXQ6IFwiZ2l0IHZlcnNpb24gMi4zOS4yXCJcbiAgICAvLyBucG0gdmVyc2lvbiBvdXRwdXQ6IFwiOC4xOS4yXCIgb3IgSlNPTiB3aXRoIHZlcnNpb24gaW5mb1xuICAgIFxuICAgIGlmICh0b29sID09PSAnZ2l0Jykge1xuICAgICAgY29uc3QgbWF0Y2ggPSBvdXRwdXQubWF0Y2goL2dpdCB2ZXJzaW9uIChcXGQrXFwuXFxkK1xcLlxcZCspLyk7XG4gICAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gICAgfSBlbHNlIGlmICh0b29sID09PSAnbnBtJykge1xuICAgICAgLy8gbnBtIG1pZ2h0IHJldHVybiBqdXN0IHRoZSB2ZXJzaW9uIG51bWJlciBvciBKU09OXG4gICAgICBjb25zdCBjbGVhbk91dHB1dCA9IG91dHB1dC50cmltKCk7XG4gICAgICBpZiAoY2xlYW5PdXRwdXQubWF0Y2goL15cXGQrXFwuXFxkK1xcLlxcZCsvKSkge1xuICAgICAgICByZXR1cm4gY2xlYW5PdXRwdXQuc3BsaXQoJ1xcbicpWzBdOyAvLyBGaXJzdCBsaW5lIGlmIG11bHRpcGxlIGxpbmVzXG4gICAgICB9XG4gICAgICAvLyBUcnkgdG8gcGFyc2UgYXMgSlNPTiBpZiBpdCBsb29rcyBsaWtlIEpTT05cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY2xlYW5PdXRwdXQpO1xuICAgICAgICByZXR1cm4gcGFyc2VkLm5wbSB8fCBwYXJzZWQudmVyc2lvbiB8fCBudWxsO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIElmIG5vdCBKU09OLCB0cnkgdG8gZXh0cmFjdCB2ZXJzaW9uIHBhdHRlcm5cbiAgICAgICAgY29uc3QgbWF0Y2ggPSBjbGVhbk91dHB1dC5tYXRjaCgvKFxcZCtcXC5cXGQrXFwuXFxkKykvKTtcbiAgICAgICAgcmV0dXJuIG1hdGNoID8gbWF0Y2hbMV0gOiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYSBkZXBlbmRlbmN5IHZlcnNpb24gbWVldHMgcmVxdWlyZW1lbnRzXG4gICAqL1xuICB2YWxpZGF0ZURlcGVuZGVuY3lWZXJzaW9uKFxuICAgIGFjdHVhbFZlcnNpb246IHN0cmluZywgXG4gICAgcmVxdWlyZW1lbnRzOiB7IG1pbmltdW06IHN0cmluZzsgbWF4aW11bTogc3RyaW5nOyByZWNvbW1lbmRlZDogc3RyaW5nIH0sXG4gICAgdG9vbE5hbWU6IHN0cmluZ1xuICApOiB7IHZhbGlkOiBib29sZWFuOyB3YXJuaW5nPzogc3RyaW5nOyBlcnJvcj86IHN0cmluZyB9IHtcbiAgICBjb25zdCBtaW5Db21wYXJpc29uID0gdGhpcy5jb21wYXJlVmVyc2lvbnMoYWN0dWFsVmVyc2lvbiwgcmVxdWlyZW1lbnRzLm1pbmltdW0pO1xuICAgIGNvbnN0IG1heENvbXBhcmlzb24gPSB0aGlzLmNvbXBhcmVWZXJzaW9ucyhhY3R1YWxWZXJzaW9uLCByZXF1aXJlbWVudHMubWF4aW11bSk7XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgdmVyc2lvbiBpcyBiZWxvdyBtaW5pbXVtXG4gICAgaWYgKG1pbkNvbXBhcmlzb24gPCAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWxpZDogZmFsc2UsXG4gICAgICAgIGVycm9yOiBgJHt0b29sTmFtZX0gdmVyc2lvbiAke2FjdHVhbFZlcnNpb259IGlzIGJlbG93IG1pbmltdW0gcmVxdWlyZWQgdmVyc2lvbiAke3JlcXVpcmVtZW50cy5taW5pbXVtfS4gUGxlYXNlIHVwZ3JhZGUgJHt0b29sTmFtZX0uYFxuICAgICAgfTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgdmVyc2lvbiBpcyBhYm92ZSBtYXhpbXVtIHRlc3RlZFxuICAgIGlmIChtYXhDb21wYXJpc29uID4gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsaWQ6IHRydWUsXG4gICAgICAgIHdhcm5pbmc6IGAke3Rvb2xOYW1lfSB2ZXJzaW9uICR7YWN0dWFsVmVyc2lvbn0gaXMgYWJvdmUgbWF4aW11bSB0ZXN0ZWQgdmVyc2lvbiAke3JlcXVpcmVtZW50cy5tYXhpbXVtfS4gU29tZSBmZWF0dXJlcyBtYXkgbm90IHdvcmsgYXMgZXhwZWN0ZWQuYFxuICAgICAgfTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgbm90IGF0IHJlY29tbWVuZGVkIHZlcnNpb25cbiAgICBjb25zdCByZWNDb21wYXJpc29uID0gdGhpcy5jb21wYXJlVmVyc2lvbnMoYWN0dWFsVmVyc2lvbiwgcmVxdWlyZW1lbnRzLnJlY29tbWVuZGVkKTtcbiAgICBpZiAocmVjQ29tcGFyaXNvbiAhPT0gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsaWQ6IHRydWUsXG4gICAgICAgIHdhcm5pbmc6IGAke3Rvb2xOYW1lfSB2ZXJzaW9uICR7YWN0dWFsVmVyc2lvbn0gd29ya3MgYnV0ICR7cmVxdWlyZW1lbnRzLnJlY29tbWVuZGVkfSBpcyByZWNvbW1lbmRlZCBmb3Igb3B0aW1hbCBzdGFiaWxpdHkuYFxuICAgICAgfTtcbiAgICB9XG4gICAgXG4gICAgLy8gVmVyc2lvbiBpcyBwZXJmZWN0XG4gICAgcmV0dXJuIHsgdmFsaWQ6IHRydWUgfTtcbiAgfVxufSJdfQ==