claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
180 lines (157 loc) • 5.51 kB
text/typescript
/**
* Package validator for update compatibility
* Ensures updates don't break the ecosystem
*/
import * as semver from 'semver';
export interface ValidationResult {
valid: boolean;
incompatibilities: string[];
warnings: string[];
requiredPeerUpdates: string[];
}
interface PackageCompatibility {
minVersion: string;
maxVersion?: string;
peerDependencies?: Record<string, string>;
}
// Known compatibility matrix between @claude-flow packages
const COMPATIBILITY_MATRIX: Record<string, Record<string, PackageCompatibility>> = {
'@claude-flow/cli': {
'@claude-flow/embeddings': { minVersion: '3.0.0-alpha.1' },
'@claude-flow/security': { minVersion: '3.0.0-alpha.1' },
'@claude-flow/integration': { minVersion: '3.0.0-alpha.1' },
},
'@claude-flow/embeddings': {
'@claude-flow/cli': { minVersion: '3.0.0-alpha.50' },
},
'@claude-flow/integration': {
'@claude-flow/cli': { minVersion: '3.0.0-alpha.70' },
'agentic-flow': { minVersion: '3.0.0-alpha.1' },
},
};
// Known breaking changes by version
const BREAKING_CHANGES: Record<string, Record<string, string[]>> = {
'@claude-flow/cli': {
'3.0.0': [
'Memory API changed from key-value to vector-based',
'Hooks system completely redesigned',
'Agent spawning now requires type parameter',
],
},
'@claude-flow/embeddings': {
'3.0.0': [
'Switched from better-sqlite3 to sql.js',
'New initialization required with initEmbeddings()',
],
},
};
export function validateUpdate(
packageName: string,
fromVersion: string,
toVersion: string,
installedPackages: Record<string, string>
): ValidationResult {
const result: ValidationResult = {
valid: true,
incompatibilities: [],
warnings: [],
requiredPeerUpdates: [],
};
// Check if this is a major version bump
if (semver.valid(fromVersion) && semver.valid(toVersion)) {
const fromMajor = semver.major(fromVersion);
const toMajor = semver.major(toVersion);
if (toMajor > fromMajor) {
result.warnings.push(
`Major version update (${fromMajor} → ${toMajor}) may contain breaking changes`
);
// Check for known breaking changes
const changes = BREAKING_CHANGES[packageName]?.[`${toMajor}.0.0`];
if (changes) {
result.warnings.push(`Known breaking changes in v${toMajor}:`);
changes.forEach((change) => result.warnings.push(` - ${change}`));
}
}
}
// Check compatibility with installed packages
const compatibility = COMPATIBILITY_MATRIX[packageName];
if (compatibility) {
for (const [depName, depReq] of Object.entries(compatibility)) {
const installedVersion = installedPackages[depName];
if (installedVersion) {
// Check minimum version
if (
semver.valid(installedVersion) &&
semver.lt(installedVersion, depReq.minVersion)
) {
result.incompatibilities.push(
`${packageName}@${toVersion} requires ${depName} >= ${depReq.minVersion} (installed: ${installedVersion})`
);
result.requiredPeerUpdates.push(`${depName}@>=${depReq.minVersion}`);
result.valid = false;
}
// Check maximum version
if (
depReq.maxVersion &&
semver.valid(installedVersion) &&
semver.gt(installedVersion, depReq.maxVersion)
) {
result.warnings.push(
`${packageName}@${toVersion} may not be compatible with ${depName}@${installedVersion} (max: ${depReq.maxVersion})`
);
}
}
}
}
// Check reverse compatibility - other packages that depend on this one
for (const [pkgName, deps] of Object.entries(COMPATIBILITY_MATRIX)) {
if (pkgName === packageName) continue;
const depInfo = deps[packageName];
if (depInfo && installedPackages[pkgName]) {
// If the target version is below what the installed package needs
if (semver.valid(toVersion) && semver.lt(toVersion, depInfo.minVersion)) {
result.incompatibilities.push(
`${pkgName}@${installedPackages[pkgName]} requires ${packageName} >= ${depInfo.minVersion}`
);
result.valid = false;
}
}
}
return result;
}
export function validateBulkUpdate(
updates: Array<{ package: string; from: string; to: string }>,
currentPackages: Record<string, string>
): ValidationResult {
const combinedResult: ValidationResult = {
valid: true,
incompatibilities: [],
warnings: [],
requiredPeerUpdates: [],
};
// Create a simulated state after all updates
const simulatedPackages = { ...currentPackages };
for (const update of updates) {
simulatedPackages[update.package] = update.to;
}
// Validate each update against the final state
for (const update of updates) {
const result = validateUpdate(
update.package,
update.from,
update.to,
simulatedPackages
);
if (!result.valid) {
combinedResult.valid = false;
}
combinedResult.incompatibilities.push(...result.incompatibilities);
combinedResult.warnings.push(...result.warnings);
combinedResult.requiredPeerUpdates.push(...result.requiredPeerUpdates);
}
// Deduplicate
combinedResult.incompatibilities = [...new Set(combinedResult.incompatibilities)];
combinedResult.warnings = [...new Set(combinedResult.warnings)];
combinedResult.requiredPeerUpdates = [...new Set(combinedResult.requiredPeerUpdates)];
return combinedResult;
}