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
437 lines (380 loc) • 12.1 kB
text/typescript
/**
* SDK Bridge for agentic-flow API Compatibility
*
* Provides API compatibility layer between claude-flow v3 and
* agentic-flow@alpha, handling version negotiation, feature
* detection, and fallback behavior.
*
* Key Responsibilities:
* - Version negotiation and compatibility checking
* - API translation for v2 -> v3 migration
* - Feature detection and graceful degradation
* - Deprecated API support with warnings
*
* @module v3/integration/sdk-bridge
* @version 3.0.0-alpha.1
*/
import { EventEmitter } from 'events';
import type {
SDKBridgeConfig,
SDKVersion,
SDKCompatibility,
} from './types.js';
/**
* Feature availability by SDK version
*/
const FEATURE_MATRIX: Record<string, { minVersion: string; optional: boolean }> = {
'sona-learning': { minVersion: '2.0.0', optional: false },
'flash-attention': { minVersion: '2.0.0', optional: false },
'agentdb-hnsw': { minVersion: '2.0.0', optional: false },
'gnn-refinement': { minVersion: '2.0.0', optional: true },
'trajectory-tracking': { minVersion: '2.0.0', optional: false },
'intelligence-bridge': { minVersion: '2.0.1', optional: false },
'quic-transport': { minVersion: '2.0.1', optional: true },
'nightly-learning': { minVersion: '2.0.1', optional: true },
'micro-lora': { minVersion: '2.0.1', optional: true },
};
/**
* Deprecated API mappings (old -> new)
*/
const DEPRECATED_API_MAP: Record<string, {
replacement: string;
since: string;
removed?: string;
transformer?: (args: unknown[]) => unknown[];
}> = {
'ReasoningBank.initialize': {
replacement: 'HybridReasoningBank.initialize',
since: '2.0.0',
},
'AgentDB.store': {
replacement: 'AgentDBFast.store',
since: '2.0.0',
transformer: (args) => args, // Same signature
},
'computeEmbedding': {
replacement: 'EmbeddingService.compute',
since: '2.0.0',
},
};
/**
* SDKBridge - API Compatibility Layer
*
* This bridge handles version compatibility, feature detection,
* and API translation between claude-flow and agentic-flow.
*/
export class SDKBridge extends EventEmitter {
private config: SDKBridgeConfig;
private initialized: boolean = false;
private currentVersion: SDKVersion | null = null;
private availableFeatures: Set<string> = new Set();
private deprecationWarnings: Set<string> = new Set();
constructor(config: Partial<SDKBridgeConfig> = {}) {
super();
this.config = this.mergeConfig(config);
}
/**
* Initialize the SDK bridge
*/
async initialize(): Promise<void> {
if (this.initialized) {
return;
}
this.emit('initializing');
try {
// Detect SDK version
this.currentVersion = await this.detectVersion();
// Check compatibility
const compatibility = await this.checkCompatibility();
if (!compatibility.compatible) {
throw new Error(
`SDK version ${this.currentVersion.full} is not compatible. ` +
`Required: ${compatibility.minVersion.full} - ${compatibility.maxVersion.full}`
);
}
// Detect available features
await this.detectFeatures();
this.initialized = true;
this.emit('initialized', {
version: this.currentVersion,
features: Array.from(this.availableFeatures)
});
} catch (error) {
this.emit('initialization-failed', { error });
throw error;
}
}
/**
* Ping to check if SDK is available
*/
async ping(): Promise<boolean> {
// Simple health check
return this.initialized;
}
/**
* Get current SDK version
*/
getVersion(): SDKVersion | null {
return this.currentVersion;
}
/**
* Check if a feature is available
*/
isFeatureAvailable(feature: string): boolean {
return this.availableFeatures.has(feature);
}
/**
* Get all available features
*/
getAvailableFeatures(): string[] {
return Array.from(this.availableFeatures);
}
/**
* Get compatibility information
*/
async checkCompatibility(): Promise<SDKCompatibility> {
const current = this.currentVersion || await this.detectVersion();
const minVersion = this.parseVersion('2.0.0-alpha.0');
const maxVersion = this.parseVersion('3.0.0');
const compatible =
this.compareVersions(current, minVersion) >= 0 &&
this.compareVersions(current, maxVersion) < 0;
const requiredFeatures = Object.entries(FEATURE_MATRIX)
.filter(([_, info]) => !info.optional)
.map(([name]) => name);
const optionalFeatures = Object.entries(FEATURE_MATRIX)
.filter(([_, info]) => info.optional)
.map(([name]) => name);
return {
minVersion,
maxVersion,
currentVersion: current,
compatible,
requiredFeatures,
optionalFeatures,
};
}
/**
* Translate deprecated API call to new API
*/
translateDeprecatedAPI(
oldAPI: string,
args: unknown[]
): { newAPI: string; args: unknown[] } | null {
const mapping = DEPRECATED_API_MAP[oldAPI];
if (!mapping) {
return null;
}
// Emit deprecation warning (once per API)
if (!this.deprecationWarnings.has(oldAPI)) {
this.deprecationWarnings.add(oldAPI);
const message = `'${oldAPI}' is deprecated since ${mapping.since}. ` +
`Use '${mapping.replacement}' instead.`;
switch (this.config.fallbackBehavior) {
case 'error':
throw new Error(message);
case 'warn':
console.warn(`[DEPRECATED] ${message}`);
this.emit('deprecation-warning', { oldAPI, mapping });
break;
case 'silent':
// Log but don't warn
break;
}
}
const newArgs = mapping.transformer ? mapping.transformer(args) : args;
return { newAPI: mapping.replacement, args: newArgs };
}
/**
* Wrap an API call with compatibility handling
*/
async wrapAPICall<T>(
apiName: string,
apiCall: () => Promise<T>,
fallback?: () => Promise<T>
): Promise<T> {
this.ensureInitialized();
try {
return await apiCall();
} catch (error) {
// Check if this is a version-related error
if (this.isVersionError(error)) {
if (fallback) {
this.emit('fallback-used', { apiName, error });
return await fallback();
}
}
throw error;
}
}
/**
* Get feature requirements for a capability
*/
getFeatureRequirements(capability: string): {
required: string[];
optional: string[];
satisfied: boolean;
} {
const capabilityFeatures: Record<string, { required: string[]; optional: string[] }> = {
'learning': {
required: ['sona-learning', 'trajectory-tracking'],
optional: ['nightly-learning', 'micro-lora'],
},
'attention': {
required: ['flash-attention'],
optional: [],
},
'search': {
required: ['agentdb-hnsw'],
optional: ['gnn-refinement'],
},
'coordination': {
required: ['sona-learning', 'flash-attention'],
optional: ['quic-transport'],
},
};
const features = capabilityFeatures[capability] || { required: [], optional: [] };
const satisfied = features.required.every(f => this.availableFeatures.has(f));
return {
...features,
satisfied,
};
}
/**
* Negotiate version with remote SDK
*/
async negotiateVersion(preferredVersion?: string): Promise<SDKVersion> {
// In a real implementation, this would communicate with the SDK
// to determine the best compatible version to use
const preferred = preferredVersion
? this.parseVersion(preferredVersion)
: this.currentVersion;
if (!preferred) {
return this.currentVersion || this.parseVersion('2.0.1-alpha.50');
}
// Return the negotiated version
return preferred;
}
/**
* Get migration guide for deprecated APIs
*/
getMigrationGuide(): Record<string, {
old: string;
new: string;
example: string;
}> {
const guide: Record<string, { old: string; new: string; example: string }> = {};
for (const [oldAPI, mapping] of Object.entries(DEPRECATED_API_MAP)) {
guide[oldAPI] = {
old: oldAPI,
new: mapping.replacement,
example: this.generateMigrationExample(oldAPI, mapping.replacement),
};
}
return guide;
}
/**
* Shutdown the bridge
*/
async shutdown(): Promise<void> {
this.initialized = false;
this.availableFeatures.clear();
this.deprecationWarnings.clear();
this.emit('shutdown');
}
// ===== Private Methods =====
private mergeConfig(config: Partial<SDKBridgeConfig>): SDKBridgeConfig {
return {
targetVersion: config.targetVersion || 'alpha',
enableVersionNegotiation: config.enableVersionNegotiation ?? true,
fallbackBehavior: config.fallbackBehavior || 'warn',
enableCompatibilityLayer: config.enableCompatibilityLayer ?? true,
supportDeprecatedAPIs: config.supportDeprecatedAPIs ?? true,
};
}
private async detectVersion(): Promise<SDKVersion> {
// Detect agentic-flow version dynamically
try {
const af = await import('agentic-flow');
const version = (af as Record<string, unknown>)['VERSION'] as string | undefined;
if (version) {
return this.parseVersion(version);
}
} catch {
// agentic-flow not available, use fallback version
}
return this.parseVersion('2.0.1-alpha.50');
}
private async detectFeatures(): Promise<void> {
if (!this.currentVersion) {
return;
}
for (const [feature, info] of Object.entries(FEATURE_MATRIX)) {
const minVersion = this.parseVersion(info.minVersion);
if (this.compareVersions(this.currentVersion, minVersion) >= 0) {
this.availableFeatures.add(feature);
}
}
this.emit('features-detected', {
features: Array.from(this.availableFeatures)
});
}
private parseVersion(version: string): SDKVersion {
// Handle versions like "2.0.1-alpha.50" or "2.0.0"
const parts = version.split('-');
const core = parts[0].split('.');
const prerelease = parts[1] || undefined;
return {
major: parseInt(core[0] || '0', 10),
minor: parseInt(core[1] || '0', 10),
patch: parseInt(core[2] || '0', 10),
prerelease,
full: version,
};
}
private compareVersions(a: SDKVersion, b: SDKVersion): number {
// Compare major, minor, patch
if (a.major !== b.major) return a.major - b.major;
if (a.minor !== b.minor) return a.minor - b.minor;
if (a.patch !== b.patch) return a.patch - b.patch;
// Compare prerelease (alpha < beta < rc < release)
if (!a.prerelease && b.prerelease) return 1;
if (a.prerelease && !b.prerelease) return -1;
if (!a.prerelease && !b.prerelease) return 0;
// Both have prerelease
return (a.prerelease || '').localeCompare(b.prerelease || '');
}
private isVersionError(error: unknown): boolean {
const message = (error as Error)?.message || '';
return message.includes('version') ||
message.includes('not supported') ||
message.includes('deprecated');
}
private generateMigrationExample(oldAPI: string, newAPI: string): string {
// Generate a simple migration example
const oldParts = oldAPI.split('.');
const newParts = newAPI.split('.');
const oldCall = oldParts.length > 1
? `${oldParts[0]}.${oldParts[1]}(args)`
: `${oldAPI}(args)`;
const newCall = newParts.length > 1
? `new ${newParts[0]}().${newParts[1]}(args)`
: `${newAPI}(args)`;
return `// Before:\n${oldCall}\n\n// After:\n${newCall}`;
}
private ensureInitialized(): void {
if (!this.initialized) {
throw new Error('SDKBridge not initialized. Call initialize() first.');
}
}
}
/**
* Create and initialize an SDK bridge
*/
export async function createSDKBridge(
config?: Partial<SDKBridgeConfig>
): Promise<SDKBridge> {
const bridge = new SDKBridge(config);
await bridge.initialize();
return bridge;
}