/** * Felix Framework - Interactive Parameter Controls * * Type-safe parameter controls for Felix Framework configuration with * real-time validation, constraint enforcement, and mobile-optimized * input handling for helix geometry, agent configuration, and system settings. * * Features: * - Type-safe parameter validation * - Real-time constraint checking * - Dependency resolution between parameters * - Mobile-optimized input controls * - Undo/redo functionality * - Parameter presets and templates * - Export/import configurations * - Performance impact prediction * * @version 1.0.0 * @author Felix Framework Team */ import { GradioSlider, GradioTextbox, GradioCheckboxGroup, GradioDropdown, GradioCheckbox, ValidationResult, ValidationError, ValidationWarning } from '../types/gradio-interface'; import { HelixGeometry, AgentConfig, AgentType, TaskRequirements, PerformanceMetrics, Radius, Turns, Height, HelixParameter } from '../types/felix-core'; // ============================================================================= // Parameter Control Types // ============================================================================= /** Parameter control configuration */ export interface ParameterControlConfig { readonly id: string; readonly label: string; readonly description?: string; readonly type: ParameterType; readonly constraints: ParameterConstraints; readonly defaultValue: unknown; readonly dependencies?: readonly string[]; readonly mobileOptimized?: boolean; readonly performanceImpact?: PerformanceImpact; } /** Parameter types */ export enum ParameterType { Number = 'number', Integer = 'integer', Float = 'float', Boolean = 'boolean', String = 'string', Enum = 'enum', Range = 'range', MultiSelect = 'multi_select' } /** Parameter constraints */ export interface ParameterConstraints { readonly min?: number; readonly max?: number; readonly step?: number; readonly precision?: number; readonly options?: readonly string[]; readonly pattern?: RegExp; readonly required?: boolean; readonly customValidator?: (value: unknown) => ValidationResult; } /** Performance impact levels */ export enum PerformanceImpact { None = 'none', Low = 'low', Medium = 'medium', High = 'high', Critical = 'critical' } // ============================================================================= // Helix Geometry Parameter Controls // ============================================================================= /** Helix geometry parameter configuration */ export interface HelixGeometryParams { readonly topRadius: number; readonly bottomRadius: number; readonly height: number; readonly turns: number; readonly resolution: number; readonly mathematicalPrecision: number; } /** Helix parameter control definitions */ export const HELIX_PARAMETER_CONTROLS: Record = { topRadius: { id: 'helix_top_radius', label: 'Top Radius', description: 'Radius at the top of the helix (broad exploration phase)', type: ParameterType.Float, constraints: { min: 0.1, max: 100.0, step: 0.1, precision: 3, required: true, customValidator: (value) => validateRadius(value as number, 'top') }, defaultValue: 33.0, dependencies: ['bottomRadius'], performanceImpact: PerformanceImpact.Medium }, bottomRadius: { id: 'helix_bottom_radius', label: 'Bottom Radius', description: 'Radius at the bottom of the helix (focused synthesis phase)', type: ParameterType.Float, constraints: { min: 0.001, max: 10.0, step: 0.001, precision: 6, required: true, customValidator: (value) => validateRadius(value as number, 'bottom') }, defaultValue: 0.001, dependencies: ['topRadius'], performanceImpact: PerformanceImpact.Low }, height: { id: 'helix_height', label: 'Helix Height', description: 'Total height of the helix structure', type: ParameterType.Float, constraints: { min: 10.0, max: 1000.0, step: 1.0, precision: 1, required: true }, defaultValue: 100.0, performanceImpact: PerformanceImpact.Low }, turns: { id: 'helix_turns', label: 'Number of Turns', description: 'Complete rotations in the helix (affects agent path complexity)', type: ParameterType.Integer, constraints: { min: 1, max: 100, step: 1, required: true, customValidator: validateTurns }, defaultValue: 33, dependencies: ['resolution'], performanceImpact: PerformanceImpact.High }, resolution: { id: 'helix_resolution', label: 'Visualization Resolution', description: 'Number of points used for helix visualization (affects rendering performance)', type: ParameterType.Integer, constraints: { min: 50, max: 2000, step: 50, required: true }, defaultValue: 500, mobileOptimized: true, performanceImpact: PerformanceImpact.Critical }, mathematicalPrecision: { id: 'helix_precision', label: 'Mathematical Precision', description: 'Precision threshold for mathematical calculations (scientific notation)', type: ParameterType.Float, constraints: { min: 1e-15, max: 1e-6, step: 1e-15, precision: 15 }, defaultValue: 1e-12, performanceImpact: PerformanceImpact.None } }; // ============================================================================= // Agent Configuration Parameter Controls // ============================================================================= /** Agent configuration parameters */ export interface AgentConfigParams { readonly maxAgents: number; readonly spawnInterval: number; readonly agentTypes: readonly AgentType[]; readonly temperatureSettings: Record; readonly lifetimeSettings: Record; readonly enableAdaptiveSpawning: boolean; readonly enableLoadBalancing: boolean; } /** Agent parameter control definitions */ export const AGENT_PARAMETER_CONTROLS: Record = { maxAgents: { id: 'agent_max_count', label: 'Maximum Agents', description: 'Maximum number of concurrent agents (affects memory usage)', type: ParameterType.Integer, constraints: { min: 1, max: 100, step: 1, required: true, customValidator: validateMaxAgents }, defaultValue: 20, performanceImpact: PerformanceImpact.Critical }, spawnInterval: { id: 'agent_spawn_interval', label: 'Spawn Interval (ms)', description: 'Time between agent spawns in milliseconds', type: ParameterType.Integer, constraints: { min: 100, max: 10000, step: 100, required: true }, defaultValue: 1000, performanceImpact: PerformanceImpact.Medium }, agentTypes: { id: 'agent_types_enabled', label: 'Enabled Agent Types', description: 'Select which agent types are available for spawning', type: ParameterType.MultiSelect, constraints: { options: Object.values(AgentType), required: true, customValidator: validateAgentTypes }, defaultValue: [AgentType.Research, AgentType.Analysis, AgentType.Synthesis], performanceImpact: PerformanceImpact.Medium }, enableAdaptiveSpawning: { id: 'agent_adaptive_spawning', label: 'Adaptive Spawning', description: 'Automatically adjust agent spawning based on task complexity', type: ParameterType.Boolean, constraints: { required: false }, defaultValue: true, performanceImpact: PerformanceImpact.Low }, enableLoadBalancing: { id: 'agent_load_balancing', label: 'Load Balancing', description: 'Distribute tasks evenly across available agents', type: ParameterType.Boolean, constraints: { required: false }, defaultValue: true, performanceImpact: PerformanceImpact.Low } }; // ============================================================================= // System Performance Parameter Controls // ============================================================================= /** System performance parameters */ export interface SystemPerformanceParams { readonly updateInterval: number; readonly renderingMode: RenderingMode; readonly memoryLimit: number; readonly enableGPU: boolean; readonly compressionLevel: number; readonly cacheSize: number; readonly logLevel: LogLevel; } /** Rendering modes */ export enum RenderingMode { Quality = 'quality', Balanced = 'balanced', Performance = 'performance', Mobile = 'mobile' } /** Log levels */ export enum LogLevel { Debug = 'debug', Info = 'info', Warning = 'warning', Error = 'error' } /** System parameter control definitions */ export const SYSTEM_PARAMETER_CONTROLS: Record = { updateInterval: { id: 'system_update_interval', label: 'Update Interval (ms)', description: 'How often the system updates visualization and metrics', type: ParameterType.Integer, constraints: { min: 16, max: 5000, step: 16, required: true }, defaultValue: 500, mobileOptimized: true, performanceImpact: PerformanceImpact.High }, renderingMode: { id: 'system_rendering_mode', label: 'Rendering Mode', description: 'Balance between visual quality and performance', type: ParameterType.Enum, constraints: { options: Object.values(RenderingMode), required: true }, defaultValue: RenderingMode.Balanced, mobileOptimized: true, performanceImpact: PerformanceImpact.Critical }, memoryLimit: { id: 'system_memory_limit', label: 'Memory Limit (MB)', description: 'Maximum memory usage for the application', type: ParameterType.Integer, constraints: { min: 100, max: 8000, step: 100, required: true }, defaultValue: 1000, performanceImpact: PerformanceImpact.High }, enableGPU: { id: 'system_enable_gpu', label: 'GPU Acceleration', description: 'Use GPU for compute-intensive operations when available', type: ParameterType.Boolean, constraints: { required: false, customValidator: validateGPUAvailability }, defaultValue: true, performanceImpact: PerformanceImpact.Critical }, compressionLevel: { id: 'system_compression_level', label: 'Data Compression', description: 'Level of compression for data transfer (0=none, 9=maximum)', type: ParameterType.Integer, constraints: { min: 0, max: 9, step: 1, required: true }, defaultValue: 3, performanceImpact: PerformanceImpact.Medium }, cacheSize: { id: 'system_cache_size', label: 'Cache Size (MB)', description: 'Size of rendering and data cache', type: ParameterType.Integer, constraints: { min: 10, max: 500, step: 10, required: true }, defaultValue: 100, performanceImpact: PerformanceImpact.Medium }, logLevel: { id: 'system_log_level', label: 'Log Level', description: 'Minimum level for system logging', type: ParameterType.Enum, constraints: { options: Object.values(LogLevel), required: true }, defaultValue: LogLevel.Info, performanceImpact: PerformanceImpact.Low } }; // ============================================================================= // Parameter Control Manager // ============================================================================= export class ParameterControlManager { private currentValues: Map = new Map(); private parameterHistory: ParameterHistoryEntry[] = []; private validationResults: Map = new Map(); private dependencyGraph: Map> = new Map(); private changeListeners: Map> = new Map(); constructor(private readonly isMobile: boolean = false) { this.initializeParameters(); this.buildDependencyGraph(); } // ============================================================================= // Parameter Management // ============================================================================= /** * Initialize parameters with default values */ private initializeParameters(): void { const allControls = { ...HELIX_PARAMETER_CONTROLS, ...AGENT_PARAMETER_CONTROLS, ...SYSTEM_PARAMETER_CONTROLS }; Object.values(allControls).forEach(control => { let defaultValue = control.defaultValue; // Apply mobile optimizations if (this.isMobile && control.mobileOptimized) { defaultValue = this.getMobileOptimizedValue(control); } this.currentValues.set(control.id, defaultValue); }); } /** * Get mobile-optimized parameter values */ private getMobileOptimizedValue(control: ParameterControlConfig): unknown { switch (control.id) { case 'helix_resolution': return Math.min(control.defaultValue as number, 200); case 'system_update_interval': return Math.max(control.defaultValue as number, 1000); case 'system_rendering_mode': return RenderingMode.Mobile; default: return control.defaultValue; } } /** * Build dependency graph for parameter relationships */ private buildDependencyGraph(): void { const allControls = { ...HELIX_PARAMETER_CONTROLS, ...AGENT_PARAMETER_CONTROLS, ...SYSTEM_PARAMETER_CONTROLS }; Object.values(allControls).forEach(control => { if (control.dependencies) { control.dependencies.forEach(depId => { if (!this.dependencyGraph.has(depId)) { this.dependencyGraph.set(depId, new Set()); } this.dependencyGraph.get(depId)!.add(control.id); }); } }); } /** * Set parameter value with validation and dependency checking */ public setParameter(parameterId: string, value: unknown): ValidationResult { const control = this.getParameterControl(parameterId); if (!control) { return { valid: false, errors: [{ field: parameterId, message: 'Parameter not found', code: 'NOT_FOUND' }], warnings: [] }; } // Validate the value const validationResult = this.validateParameter(control, value); if (!validationResult.valid) { this.validationResults.set(parameterId, validationResult); return validationResult; } // Store previous value for history const previousValue = this.currentValues.get(parameterId); // Update value this.currentValues.set(parameterId, value); this.validationResults.set(parameterId, validationResult); // Add to history this.addToHistory(parameterId, previousValue, value); // Validate dependent parameters this.validateDependencies(parameterId); // Notify listeners this.notifyChangeListeners(parameterId, value, previousValue); return validationResult; } /** * Get parameter value */ public getParameter(parameterId: string): T | undefined { return this.currentValues.get(parameterId) as T; } /** * Get all parameter values */ public getAllParameters(): Record { const result: Record = {}; this.currentValues.forEach((value, key) => { result[key] = value; }); return result; } /** * Reset parameters to defaults */ public resetToDefaults(): void { this.currentValues.clear(); this.validationResults.clear(); this.parameterHistory.length = 0; this.initializeParameters(); } // ============================================================================= // Validation // ============================================================================= /** * Validate a parameter value */ private validateParameter(control: ParameterControlConfig, value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; // Type validation if (!this.validateType(control.type, value)) { errors.push({ field: control.id, message: `Invalid type. Expected ${control.type}`, code: 'INVALID_TYPE' }); return { valid: false, errors, warnings }; } // Constraint validation const constraintResult = this.validateConstraints(control.constraints, value); errors.push(...constraintResult.errors); warnings.push(...constraintResult.warnings); // Custom validation if (control.constraints.customValidator) { const customResult = control.constraints.customValidator(value); errors.push(...customResult.errors); warnings.push(...customResult.warnings); } // Performance impact warning if (control.performanceImpact === PerformanceImpact.Critical) { warnings.push({ field: control.id, message: 'This parameter has critical performance impact', suggestion: 'Consider the effect on system performance' }); } return { valid: errors.length === 0, errors, warnings }; } /** * Validate parameter type */ private validateType(expectedType: ParameterType, value: unknown): boolean { switch (expectedType) { case ParameterType.Number: case ParameterType.Float: case ParameterType.Integer: return typeof value === 'number' && !isNaN(value); case ParameterType.Boolean: return typeof value === 'boolean'; case ParameterType.String: return typeof value === 'string'; case ParameterType.Enum: return typeof value === 'string'; case ParameterType.MultiSelect: return Array.isArray(value); case ParameterType.Range: return Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number'; default: return false; } } /** * Validate parameter constraints */ private validateConstraints(constraints: ParameterConstraints, value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; // Required validation if (constraints.required && (value === null || value === undefined || value === '')) { errors.push({ field: 'value', message: 'This parameter is required', code: 'REQUIRED' }); } // Numeric constraints if (typeof value === 'number') { if (constraints.min !== undefined && value < constraints.min) { errors.push({ field: 'value', message: `Value must be at least ${constraints.min}`, code: 'MIN_VALUE' }); } if (constraints.max !== undefined && value > constraints.max) { errors.push({ field: 'value', message: `Value must be at most ${constraints.max}`, code: 'MAX_VALUE' }); } if (constraints.step !== undefined) { const remainder = (value - (constraints.min || 0)) % constraints.step; if (Math.abs(remainder) > 1e-10) { errors.push({ field: 'value', message: `Value must be a multiple of ${constraints.step}`, code: 'STEP_VALUE' }); } } } // Options validation if (constraints.options && typeof value === 'string') { if (!constraints.options.includes(value)) { errors.push({ field: 'value', message: `Value must be one of: ${constraints.options.join(', ')}`, code: 'INVALID_OPTION' }); } } // Pattern validation if (constraints.pattern && typeof value === 'string') { if (!constraints.pattern.test(value)) { errors.push({ field: 'value', message: 'Value does not match required pattern', code: 'PATTERN_MISMATCH' }); } } return { valid: errors.length === 0, errors, warnings }; } /** * Validate dependent parameters when a parameter changes */ private validateDependencies(changedParameterId: string): void { const dependents = this.dependencyGraph.get(changedParameterId); if (!dependents) return; dependents.forEach(dependentId => { const control = this.getParameterControl(dependentId); const value = this.currentValues.get(dependentId); if (control && value !== undefined) { const result = this.validateParameter(control, value); this.validationResults.set(dependentId, result); } }); } // ============================================================================= // Gradio Integration // ============================================================================= /** * Create Gradio slider component */ public createGradioSlider(parameterId: string): GradioSlider { const control = this.getParameterControl(parameterId); if (!control) throw new Error(`Parameter ${parameterId} not found`); const value = this.getParameter(parameterId) || 0; const validation = this.validationResults.get(parameterId); return { value, label: control.label, info: control.description, visible: true, interactive: true, minimum: control.constraints.min || 0, maximum: control.constraints.max || 100, step: control.constraints.step || 1, // Additional Gradio-specific properties would be added here }; } /** * Create Gradio textbox component */ public createGradioTextbox(parameterId: string): GradioTextbox { const control = this.getParameterControl(parameterId); if (!control) throw new Error(`Parameter ${parameterId} not found`); const value = this.getParameter(parameterId) || ''; return { value, label: control.label, info: control.description, visible: true, interactive: true, placeholder: `Enter ${control.label.toLowerCase()}...`, type: control.type === ParameterType.String ? 'text' : 'text' }; } /** * Create Gradio checkbox group component */ public createGradioCheckboxGroup(parameterId: string): GradioCheckboxGroup { const control = this.getParameterControl(parameterId); if (!control) throw new Error(`Parameter ${parameterId} not found`); const value = this.getParameter(parameterId) || []; return { value, label: control.label, info: control.description, visible: true, interactive: true, choices: control.constraints.options || [] }; } /** * Create Gradio dropdown component */ public createGradioDropdown(parameterId: string): GradioDropdown { const control = this.getParameterControl(parameterId); if (!control) throw new Error(`Parameter ${parameterId} not found`); const value = this.getParameter(parameterId) || ''; return { value, label: control.label, info: control.description, visible: true, interactive: true, choices: control.constraints.options || [] }; } // ============================================================================= // Presets and Templates // ============================================================================= /** * Create parameter preset */ public createPreset(name: string, description: string): ParameterPreset { return { id: `preset_${Date.now()}`, name, description, parameters: this.getAllParameters(), createdAt: Date.now(), version: '1.0.0' }; } /** * Apply parameter preset */ public applyPreset(preset: ParameterPreset): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; Object.entries(preset.parameters).forEach(([parameterId, value]) => { const result = this.setParameter(parameterId, value); errors.push(...result.errors); warnings.push(...result.warnings); }); return { valid: errors.length === 0, errors, warnings }; } /** * Get built-in presets */ public getBuiltInPresets(): ParameterPreset[] { return [ { id: 'performance_optimized', name: 'Performance Optimized', description: 'Settings optimized for maximum performance', parameters: { 'helix_resolution': 200, 'system_rendering_mode': RenderingMode.Performance, 'system_update_interval': 1000, 'agent_max_count': 10 }, createdAt: Date.now(), version: '1.0.0' }, { id: 'quality_focused', name: 'Quality Focused', description: 'Settings optimized for visual quality', parameters: { 'helix_resolution': 1000, 'system_rendering_mode': RenderingMode.Quality, 'system_update_interval': 250, 'agent_max_count': 20 }, createdAt: Date.now(), version: '1.0.0' }, { id: 'mobile_optimized', name: 'Mobile Optimized', description: 'Settings optimized for mobile devices', parameters: { 'helix_resolution': 150, 'system_rendering_mode': RenderingMode.Mobile, 'system_update_interval': 2000, 'agent_max_count': 5, 'system_compression_level': 6 }, createdAt: Date.now(), version: '1.0.0' } ]; } // ============================================================================= // History and Undo/Redo // ============================================================================= /** * Add parameter change to history */ private addToHistory(parameterId: string, oldValue: unknown, newValue: unknown): void { this.parameterHistory.push({ parameterId, oldValue, newValue, timestamp: Date.now() }); // Limit history size if (this.parameterHistory.length > 100) { this.parameterHistory.shift(); } } /** * Undo last parameter change */ public undo(): boolean { if (this.parameterHistory.length === 0) return false; const lastChange = this.parameterHistory.pop()!; this.currentValues.set(lastChange.parameterId, lastChange.oldValue); // Re-validate const control = this.getParameterControl(lastChange.parameterId); if (control) { const result = this.validateParameter(control, lastChange.oldValue); this.validationResults.set(lastChange.parameterId, result); } return true; } /** * Get parameter change history */ public getHistory(): readonly ParameterHistoryEntry[] { return [...this.parameterHistory]; } // ============================================================================= // Event Handling // ============================================================================= /** * Add parameter change listener */ public addChangeListener(parameterId: string, listener: ParameterChangeListener): void { if (!this.changeListeners.has(parameterId)) { this.changeListeners.set(parameterId, new Set()); } this.changeListeners.get(parameterId)!.add(listener); } /** * Remove parameter change listener */ public removeChangeListener(parameterId: string, listener: ParameterChangeListener): boolean { const listeners = this.changeListeners.get(parameterId); return listeners ? listeners.delete(listener) : false; } /** * Notify change listeners */ private notifyChangeListeners(parameterId: string, newValue: unknown, oldValue: unknown): void { const listeners = this.changeListeners.get(parameterId); if (!listeners) return; listeners.forEach(listener => { try { listener(parameterId, newValue, oldValue); } catch (error) { console.error('Error in parameter change listener:', error); } }); } // ============================================================================= // Utility Methods // ============================================================================= /** * Get parameter control configuration */ private getParameterControl(parameterId: string): ParameterControlConfig | undefined { const allControls = { ...HELIX_PARAMETER_CONTROLS, ...AGENT_PARAMETER_CONTROLS, ...SYSTEM_PARAMETER_CONTROLS }; return Object.values(allControls).find(control => control.id === parameterId); } /** * Get validation result for parameter */ public getValidationResult(parameterId: string): ValidationResult | undefined { return this.validationResults.get(parameterId); } /** * Check if all parameters are valid */ public isAllValid(): boolean { return Array.from(this.validationResults.values()).every(result => result.valid); } /** * Get performance impact summary */ public getPerformanceImpact(): PerformanceImpactSummary { const impacts = Array.from(this.currentValues.keys()) .map(id => this.getParameterControl(id)) .filter(control => control?.performanceImpact) .map(control => control!.performanceImpact!); return { overall: this.calculateOverallImpact(impacts), breakdown: this.groupImpactsByLevel(impacts), recommendations: this.getPerformanceRecommendations() }; } private calculateOverallImpact(impacts: PerformanceImpact[]): PerformanceImpact { if (impacts.includes(PerformanceImpact.Critical)) return PerformanceImpact.Critical; if (impacts.includes(PerformanceImpact.High)) return PerformanceImpact.High; if (impacts.includes(PerformanceImpact.Medium)) return PerformanceImpact.Medium; if (impacts.includes(PerformanceImpact.Low)) return PerformanceImpact.Low; return PerformanceImpact.None; } private groupImpactsByLevel(impacts: PerformanceImpact[]): Record { const breakdown = { [PerformanceImpact.None]: 0, [PerformanceImpact.Low]: 0, [PerformanceImpact.Medium]: 0, [PerformanceImpact.High]: 0, [PerformanceImpact.Critical]: 0 }; impacts.forEach(impact => { breakdown[impact]++; }); return breakdown; } private getPerformanceRecommendations(): string[] { const recommendations: string[] = []; if (this.isMobile) { recommendations.push('Consider using the Mobile Optimized preset for better performance'); } const resolution = this.getParameter('helix_resolution'); if (resolution && resolution > 1000) { recommendations.push('High resolution may impact rendering performance'); } const maxAgents = this.getParameter('agent_max_count'); if (maxAgents && maxAgents > 20) { recommendations.push('High agent count may impact system performance'); } return recommendations; } } // ============================================================================= // Supporting Types and Interfaces // ============================================================================= /** Parameter preset configuration */ export interface ParameterPreset { readonly id: string; readonly name: string; readonly description: string; readonly parameters: Record; readonly createdAt: number; readonly version: string; } /** Parameter change history entry */ export interface ParameterHistoryEntry { readonly parameterId: string; readonly oldValue: unknown; readonly newValue: unknown; readonly timestamp: number; } /** Parameter change listener function */ export type ParameterChangeListener = ( parameterId: string, newValue: unknown, oldValue: unknown ) => void; /** Performance impact summary */ export interface PerformanceImpactSummary { readonly overall: PerformanceImpact; readonly breakdown: Record; readonly recommendations: readonly string[]; } // ============================================================================= // Validation Functions // ============================================================================= /** Validate radius parameters */ function validateRadius(value: number, type: 'top' | 'bottom'): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; if (type === 'top' && value < 1.0) { warnings.push({ field: 'topRadius', message: 'Very small top radius may reduce exploration effectiveness', suggestion: 'Consider using a radius of at least 1.0' }); } if (type === 'bottom' && value > 1.0) { warnings.push({ field: 'bottomRadius', message: 'Large bottom radius may reduce focus effectiveness', suggestion: 'Consider using a radius less than 1.0 for better convergence' }); } return { valid: errors.length === 0, errors, warnings }; } /** Validate number of turns */ function validateTurns(value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; const turns = value as number; if (turns > 50) { warnings.push({ field: 'turns', message: 'High number of turns may impact visualization performance', suggestion: 'Consider reducing turns for better performance' }); } if (turns < 5) { warnings.push({ field: 'turns', message: 'Low number of turns may reduce helix effectiveness', suggestion: 'Consider using at least 5 turns for proper helix geometry' }); } return { valid: errors.length === 0, errors, warnings }; } /** Validate maximum agents */ function validateMaxAgents(value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; const maxAgents = value as number; if (maxAgents > 50) { warnings.push({ field: 'maxAgents', message: 'High agent count may cause memory issues', suggestion: 'Consider reducing max agents for better stability' }); } return { valid: errors.length === 0, errors, warnings }; } /** Validate agent types selection */ function validateAgentTypes(value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; const types = value as AgentType[]; if (types.length === 0) { errors.push({ field: 'agentTypes', message: 'At least one agent type must be selected', code: 'NO_AGENTS' }); } if (!types.includes(AgentType.Synthesis)) { warnings.push({ field: 'agentTypes', message: 'Synthesis agents are recommended for task completion', suggestion: 'Consider including synthesis agents' }); } return { valid: errors.length === 0, errors, warnings }; } /** Validate GPU availability */ function validateGPUAvailability(value: unknown): ValidationResult { const errors: ValidationError[] = []; const warnings: ValidationWarning[] = []; if (value === true && !window.navigator.gpu) { warnings.push({ field: 'enableGPU', message: 'GPU not available on this device', suggestion: 'GPU acceleration will be disabled automatically' }); } return { valid: errors.length === 0, errors, warnings }; } // Export for use in Gradio interface export default ParameterControlManager;