UNPKG

@clduab11/gemini-flow

Version:

Revolutionary AI agent swarm coordination platform with Google Services integration, multimedia processing, and production-ready monitoring. Features 8 Google AI services, quantum computing capabilities, and enterprise-grade security.

827 lines (724 loc) 21.6 kB
/** * Protocol Activator * * Manages activation and coordination of A2A and MCP protocols * Provides automatic discovery and conditional loading based on environment */ import { Logger } from "../utils/logger.js"; import { featureFlags } from "../core/feature-flags.js"; import { EventEmitter } from "events"; import { RoutingStrategy } from "../types/a2a.js"; export type TopologyType = "hierarchical" | "mesh" | "ring" | "star"; export interface ProtocolConfig { name: string; version: string; enabled: boolean; autoDetect: boolean; capabilities: string[]; dependencies: string[]; ports?: number[]; endpoints?: string[]; topology?: TopologyType; } export interface ProtocolStatus { name: string; status: "inactive" | "activating" | "active" | "error" | "degraded"; version?: string; capabilities: string[]; endpoints: string[]; lastError?: string; activatedAt?: Date; metrics: { connections: number; requests: number; errors: number; avgResponseTime: number; }; } export interface ActivationResult { success: boolean; protocol: string; capabilities: string[]; endpoints: string[]; fallbacksUsed: string[]; topology: TopologyType; error?: string; } export class ProtocolActivator extends EventEmitter { private logger: Logger; private activeProtocols: Map<string, any> = new Map(); private protocolConfigs: Map<string, ProtocolConfig> = new Map(); private protocolStatus: Map<string, ProtocolStatus> = new Map(); private activationPromises: Map<string, Promise<ActivationResult>> = new Map(); constructor() { super(); this.logger = new Logger("ProtocolActivator"); this.setupProtocolConfigs(); this.performEnvironmentDetection(); } /** * Setup protocol configurations */ private setupProtocolConfigs(): void { const configs: ProtocolConfig[] = [ { name: "A2A", version: "1.0.0", enabled: false, autoDetect: true, capabilities: [ "agent-communication", "distributed-memory", "consensus-protocols", "swarm-orchestration", "capability-matching", "resource-allocation", ], dependencies: [], ports: [8080, 8081, 8082], endpoints: ["/a2a/api", "/a2a/ws", "/a2a/health"], }, { name: "MCP", version: "1.0.0", enabled: false, autoDetect: true, capabilities: [ "tool-registry", "resource-access", "capability-discovery", "protocol-bridging", "context-sharing", "secure-communication", ], dependencies: ["@modelcontextprotocol/sdk"], endpoints: ["/mcp/api", "/mcp/tools", "/mcp/resources"], }, { name: "Hybrid", version: "1.0.0", enabled: false, autoDetect: false, capabilities: [ "a2a-mcp-bridge", "protocol-translation", "unified-interface", "cross-protocol-routing", ], dependencies: [], endpoints: ["/hybrid/api", "/hybrid/bridge"], }, ]; for (const config of configs) { this.protocolConfigs.set(config.name, config); this.protocolStatus.set(config.name, { name: config.name, status: "inactive", capabilities: [], endpoints: [], metrics: { connections: 0, requests: 0, errors: 0, avgResponseTime: 0, }, }); } } /** * Perform environment detection */ private performEnvironmentDetection(): void { // Detect A2A environment this.detectA2AEnvironment(); // Detect MCP environment this.detectMCPEnvironment(); // Update feature flags based on detection this.updateFeatureFlags(); } /** * Detect A2A protocol environment */ private detectA2AEnvironment(): boolean { const indicators = [ // Environment variables process.env.A2A_ENABLED === "true", process.env.GEMINI_A2A_MODE === "true", // Configuration files this.fileExists(".a2a-config.json"), this.fileExists("a2a.config.js"), // Port availability this.checkPortsAvailable([8080, 8081]), // Feature flag featureFlags.isEnabled("a2aProtocol"), ]; const detected = indicators.some(Boolean); if (detected) { this.logger.info("A2A protocol environment detected"); const config = this.protocolConfigs.get("A2A")!; config.enabled = true; } return detected; } /** * Detect MCP protocol environment */ private detectMCPEnvironment(): boolean { const indicators = [ // Environment variables process.env.MCP_ENABLED === "true", process.env.MCP_SERVER_URL !== undefined, // Dependencies this.checkDependency("@modelcontextprotocol/sdk"), // Configuration this.fileExists(".mcp-config.json"), this.fileExists("mcp.config.js"), // Feature flag featureFlags.isEnabled("mcpProtocol"), ]; const detected = indicators.some(Boolean); if (detected) { this.logger.info("MCP protocol environment detected"); const config = this.protocolConfigs.get("MCP")!; config.enabled = true; } return detected; } /** * Update feature flags based on detection */ private updateFeatureFlags(): void { const a2aConfig = this.protocolConfigs.get("A2A")!; const mcpConfig = this.protocolConfigs.get("MCP")!; if (a2aConfig.enabled && !featureFlags.isEnabled("a2aProtocol")) { featureFlags.enable("a2aProtocol"); } if (mcpConfig.enabled && !featureFlags.isEnabled("mcpProtocol")) { featureFlags.enable("mcpProtocol"); } // Enable hybrid if both are detected if (a2aConfig.enabled && mcpConfig.enabled) { const hybridConfig = this.protocolConfigs.get("Hybrid")!; hybridConfig.enabled = true; this.logger.info("Hybrid A2A-MCP mode enabled"); } } /** * Validate topology parameter */ private validateTopology(topology: TopologyType): void { const validTopologies: TopologyType[] = [ "hierarchical", "mesh", "ring", "star", ]; if (!validTopologies.includes(topology)) { throw new Error( `Invalid topology '${topology}'. Must be one of: ${validTopologies.join(", ")}`, ); } } /** * Activate a protocol with required topology specification */ async activateProtocol( protocolName: string, topology: TopologyType, ): Promise<ActivationResult> { // Validate topology parameter this.validateTopology(topology); const config = this.protocolConfigs.get(protocolName); if (!config) { return { success: false, protocol: protocolName, capabilities: [], endpoints: [], fallbacksUsed: [], topology, error: `Unknown protocol: ${protocolName}`, }; } // Set topology in config config.topology = topology; // Return existing activation promise if in progress if (this.activationPromises.has(protocolName)) { return await this.activationPromises.get(protocolName)!; } // Create activation promise const activationPromise = this.performActivation(config, topology); this.activationPromises.set(protocolName, activationPromise); try { const result = await activationPromise; this.activationPromises.delete(protocolName); return result; } catch (error) { this.activationPromises.delete(protocolName); throw error; } } /** * Perform protocol activation */ private async performActivation( config: ProtocolConfig, topology: TopologyType, ): Promise<ActivationResult> { const startTime = performance.now(); this.logger.info(`Activating protocol: ${config.name}...`); // Update status const status = this.protocolStatus.get(config.name)!; status.status = "activating"; this.emit("protocol_activating", { protocol: config.name }); try { // Check dependencies const missingDeps = this.checkMissingDependencies(config); if (missingDeps.length > 0) { throw new Error(`Missing dependencies: ${missingDeps.join(", ")}`); } let protocolInstance: any; const fallbacksUsed: string[] = []; // Load protocol implementation switch (config.name) { case "A2A": protocolInstance = await this.activateA2AProtocol( config, topology, fallbacksUsed, ); break; case "MCP": protocolInstance = await this.activateMCPProtocol( config, topology, fallbacksUsed, ); break; case "Hybrid": protocolInstance = await this.activateHybridProtocol( config, topology, fallbacksUsed, ); break; default: throw new Error(`Unknown protocol activation: ${config.name}`); } // Store active protocol this.activeProtocols.set(config.name, protocolInstance); // Update status status.status = "active"; status.version = config.version; status.capabilities = config.capabilities; status.endpoints = config.endpoints || []; status.activatedAt = new Date(); const activationTime = performance.now() - startTime; this.logger.info(`Protocol activated: ${config.name}`, { topology: topology, activationTime: `${activationTime.toFixed(2)}ms`, capabilities: config.capabilities.length, endpoints: status.endpoints.length, fallbacks: fallbacksUsed.length, }); this.emit("protocol_activated", { protocol: config.name, topology: topology, capabilities: config.capabilities, endpoints: status.endpoints, activationTime, }); return { success: true, protocol: config.name, capabilities: config.capabilities, endpoints: status.endpoints, fallbacksUsed, topology, }; } catch (error) { // Update status status.status = "error"; status.lastError = error.message; this.logger.error(`Protocol activation failed: ${config.name}`, error); this.emit("protocol_error", { protocol: config.name, error: error.message, }); return { success: false, protocol: config.name, capabilities: [], endpoints: [], fallbacksUsed: [], topology, error: error.message, }; } } /** * Activate A2A protocol */ private async activateA2AProtocol( config: ProtocolConfig, topology: TopologyType, fallbacks: string[], ): Promise<any> { try { // Try loading full A2A implementation const { A2AProtocolManager } = await import( "./a2a/core/a2a-protocol-manager.js" ); const { A2AMessageRouter } = await import( "./a2a/core/a2a-message-router.js" ); const protocolManager = new A2AProtocolManager({ agentId: "gemini-flow-agent", topology: topology, agentCard: { id: "gemini-flow-agent", name: "Gemini Flow Agent", description: "AI assistant with multi-model capabilities", version: "1.1.0", capabilities: [], services: [], endpoints: [], metadata: { type: "coordinator", status: "idle", load: 0.1, created: Date.now(), lastSeen: Date.now(), }, }, transports: [], defaultTransport: "http", routingStrategy: this.getRoutingStrategy(topology), maxHops: this.getMaxHops(topology), discoveryEnabled: false, discoveryInterval: 60000, securityEnabled: true, trustedAgents: [], messageTimeout: 30000, maxConcurrentMessages: 10, retryPolicy: { maxAttempts: 3, backoffStrategy: "exponential", baseDelay: 1000, maxDelay: 10000, jitter: true, }, }); const messageRouter = new A2AMessageRouter(); await protocolManager.initialize(); await messageRouter.initialize(); return { protocolManager, messageRouter }; } catch (error) { this.logger.warn( "Full A2A implementation not available, trying simplified version", error.message, ); // Fallback to simplified A2A fallbacks.push("simplified-a2a"); try { const { SimpleA2AAdapter } = await import("./simple-a2a-adapter.js"); const adapter = new SimpleA2AAdapter({ topology }); await adapter.initialize(); return adapter; } catch (fallbackError) { throw new Error( `A2A activation failed: ${error.message}, fallback failed: ${fallbackError.message}`, ); } } } /** * Activate MCP protocol */ private async activateMCPProtocol( config: ProtocolConfig, topology: TopologyType, fallbacks: string[], ): Promise<any> { try { // Try loading full MCP implementation const { MCPToGeminiAdapter } = await import("../core/mcp-adapter.js"); const mcpAdapter = new MCPToGeminiAdapter("", "gemini-2.5-flash", { topology, }); // MCPToGeminiAdapter doesn't have initialize method, it initializes in constructor return mcpAdapter; } catch (error) { this.logger.warn( "Full MCP implementation not available, trying bridge mode", error.message, ); // Fallback to MCP bridge fallbacks.push("mcp-bridge"); try { const { SimpleMCPBridge } = await import("./simple-mcp-bridge.js"); const bridge = new SimpleMCPBridge({ topology }); await bridge.initialize(); return bridge; } catch (fallbackError) { throw new Error( `MCP activation failed: ${error.message}, fallback failed: ${fallbackError.message}`, ); } } } /** * Activate hybrid protocol */ private async activateHybridProtocol( config: ProtocolConfig, topology: TopologyType, fallbacks: string[], ): Promise<any> { // Ensure both A2A and MCP are active with same topology if (!this.isProtocolActive("A2A")) { await this.activateProtocol("A2A", topology); } if (!this.isProtocolActive("MCP")) { await this.activateProtocol("MCP", topology); } try { const { A2AMCPBridge } = await import("./a2a/core/a2a-mcp-bridge.js"); const bridge = new A2AMCPBridge({ topology }); // Configure bridge after instantiation if needed // bridge.configure({ // a2aProtocol: this.activeProtocols.get('A2A'), // mcpProtocol: this.activeProtocols.get('MCP') // }); await bridge.initialize(); return bridge; } catch (error) { throw new Error(`Hybrid protocol activation failed: ${error.message}`); } } /** * Deactivate a protocol */ async deactivateProtocol(protocolName: string): Promise<boolean> { const protocol = this.activeProtocols.get(protocolName); if (!protocol) { return false; } try { if (protocol.shutdown) { await protocol.shutdown(); } this.activeProtocols.delete(protocolName); const status = this.protocolStatus.get(protocolName)!; status.status = "inactive"; status.capabilities = []; status.endpoints = []; status.lastError = undefined; this.logger.info(`Protocol deactivated: ${protocolName}`); this.emit("protocol_deactivated", { protocol: protocolName }); return true; } catch (error) { this.logger.error( `Failed to deactivate protocol ${protocolName}:`, error, ); return false; } } /** * Get protocol instance */ getProtocol<T = any>(protocolName: string): T | null { return this.activeProtocols.get(protocolName) || null; } /** * Check if protocol is active */ isProtocolActive(protocolName: string): boolean { const status = this.protocolStatus.get(protocolName); return status ? status.status === "active" : false; } /** * Get protocol status */ getProtocolStatus(protocolName: string): ProtocolStatus | null { return this.protocolStatus.get(protocolName) || null; } /** * Get all protocol statuses */ getAllStatuses(): ProtocolStatus[] { return Array.from(this.protocolStatus.values()); } /** * Get routing strategy based on topology */ private getRoutingStrategy(topology: TopologyType): RoutingStrategy { switch (topology) { case "hierarchical": return "shortest_path"; case "mesh": return "load_balanced"; case "ring": return "shortest_path"; case "star": return "direct"; default: return "direct"; } } /** * Get max hops based on topology */ private getMaxHops(topology: TopologyType): number { switch (topology) { case "hierarchical": return 5; case "mesh": return 3; case "ring": return 10; case "star": return 2; default: return 3; } } /** * Auto-activate protocols based on configuration (requires topology) */ async autoActivate(topology: TopologyType): Promise<ActivationResult[]> { // Validate topology parameter this.validateTopology(topology); const results: ActivationResult[] = []; for (const [name, config] of Array.from(this.protocolConfigs.entries())) { if (config.enabled && config.autoDetect) { try { const result = await this.activateProtocol(name, topology); results.push(result); } catch (error) { results.push({ success: false, protocol: name, capabilities: [], endpoints: [], fallbacksUsed: [], topology, error: error.message, }); } } } return results; } /** * Get activation summary */ getActivationSummary(): any { const active = Array.from(this.protocolStatus.values()).filter( (s) => s.status === "active", ); const total = this.protocolStatus.size; return { total, active: active.length, inactive: total - active.length, protocols: Object.fromEntries( Array.from(this.protocolStatus.entries()).map(([name, status]) => [ name, { status: status.status, capabilities: status.capabilities.length, endpoints: status.endpoints.length, }, ]), ), capabilities: Array.from(new Set(active.flatMap((s) => s.capabilities))), mode: this.determineMode(), topology: this.getCurrentTopology(), }; } /** * Get current topology from active protocols */ private getCurrentTopology(): TopologyType | null { const activeConfigs = Array.from(this.protocolConfigs.values()).filter( (config) => config.enabled && config.topology, ); return activeConfigs.length > 0 ? activeConfigs[0].topology! : null; } /** * Determine current mode */ private determineMode(): string { const activeProtocols = Array.from(this.protocolStatus.values()) .filter((s) => s.status === "active") .map((s) => s.name); if (activeProtocols.includes("Hybrid")) { return "hybrid"; } else if ( activeProtocols.includes("A2A") && activeProtocols.includes("MCP") ) { return "dual"; } else if (activeProtocols.includes("A2A")) { return "a2a-only"; } else if (activeProtocols.includes("MCP")) { return "mcp-only"; } else { return "none"; } } // Helper methods private fileExists(filename: string): boolean { try { require("fs").accessSync(filename); return true; } catch { return false; } } private checkPortsAvailable(ports: number[]): boolean { // Simple check - in production would use actual port checking return process.env.NODE_ENV !== "production"; } private checkDependency(dep: string): boolean { try { require.resolve(dep); return true; } catch { return false; } } private checkMissingDependencies(config: ProtocolConfig): string[] { return config.dependencies.filter((dep) => !this.checkDependency(dep)); } /** * Shutdown all protocols */ async shutdown(): Promise<void> { this.logger.info("Shutting down all protocols..."); const deactivationPromises = Array.from(this.activeProtocols.keys()).map( (name) => this.deactivateProtocol(name), ); await Promise.allSettled(deactivationPromises); this.activeProtocols.clear(); this.activationPromises.clear(); this.logger.info("All protocols shut down"); } } // Export singleton instance let activatorInstance: ProtocolActivator | null = null; export function getProtocolActivator(): ProtocolActivator { if (!activatorInstance) { activatorInstance = new ProtocolActivator(); } return activatorInstance; } export function resetProtocolActivator(): void { if (activatorInstance) { activatorInstance.shutdown(); activatorInstance = null; } }