 85bf1341f3
			
		
	
	85bf1341f3
	
	
	
		
			
			Frontend Enhancements: - Complete React TypeScript frontend with modern UI components - Distributed workflows management interface with real-time updates - Socket.IO integration for live agent status monitoring - Agent management dashboard with cluster visualization - Project management interface with metrics and task tracking - Responsive design with proper error handling and loading states Backend Infrastructure: - Distributed coordinator for multi-agent workflow orchestration - Cluster management API with comprehensive agent operations - Enhanced database models for agents and projects - Project service for filesystem-based project discovery - Performance monitoring and metrics collection - Comprehensive API documentation and error handling Documentation: - Complete distributed development guide (README_DISTRIBUTED.md) - Comprehensive development report with architecture insights - System configuration templates and deployment guides The platform now provides a complete web interface for managing the distributed AI cluster with real-time monitoring, workflow orchestration, and agent coordination capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { invariant } from './errors.mjs';
 | |
| import { color } from '../value/types/color/index.mjs';
 | |
| import { clamp } from './clamp.mjs';
 | |
| import { mix } from './mix.mjs';
 | |
| import { mixColor } from './mix-color.mjs';
 | |
| import { mixComplex, mixArray, mixObject } from './mix-complex.mjs';
 | |
| import { pipe } from './pipe.mjs';
 | |
| import { progress } from './progress.mjs';
 | |
| import { noop } from './noop.mjs';
 | |
| 
 | |
| const mixNumber = (from, to) => (p) => mix(from, to, p);
 | |
| function detectMixerFactory(v) {
 | |
|     if (typeof v === "number") {
 | |
|         return mixNumber;
 | |
|     }
 | |
|     else if (typeof v === "string") {
 | |
|         return color.test(v) ? mixColor : mixComplex;
 | |
|     }
 | |
|     else if (Array.isArray(v)) {
 | |
|         return mixArray;
 | |
|     }
 | |
|     else if (typeof v === "object") {
 | |
|         return mixObject;
 | |
|     }
 | |
|     return mixNumber;
 | |
| }
 | |
| function createMixers(output, ease, customMixer) {
 | |
|     const mixers = [];
 | |
|     const mixerFactory = customMixer || detectMixerFactory(output[0]);
 | |
|     const numMixers = output.length - 1;
 | |
|     for (let i = 0; i < numMixers; i++) {
 | |
|         let mixer = mixerFactory(output[i], output[i + 1]);
 | |
|         if (ease) {
 | |
|             const easingFunction = Array.isArray(ease) ? ease[i] || noop : ease;
 | |
|             mixer = pipe(easingFunction, mixer);
 | |
|         }
 | |
|         mixers.push(mixer);
 | |
|     }
 | |
|     return mixers;
 | |
| }
 | |
| /**
 | |
|  * Create a function that maps from a numerical input array to a generic output array.
 | |
|  *
 | |
|  * Accepts:
 | |
|  *   - Numbers
 | |
|  *   - Colors (hex, hsl, hsla, rgb, rgba)
 | |
|  *   - Complex (combinations of one or more numbers or strings)
 | |
|  *
 | |
|  * ```jsx
 | |
|  * const mixColor = interpolate([0, 1], ['#fff', '#000'])
 | |
|  *
 | |
|  * mixColor(0.5) // 'rgba(128, 128, 128, 1)'
 | |
|  * ```
 | |
|  *
 | |
|  * TODO Revist this approach once we've moved to data models for values,
 | |
|  * probably not needed to pregenerate mixer functions.
 | |
|  *
 | |
|  * @public
 | |
|  */
 | |
| function interpolate(input, output, { clamp: isClamp = true, ease, mixer } = {}) {
 | |
|     const inputLength = input.length;
 | |
|     invariant(inputLength === output.length, "Both input and output ranges must be the same length");
 | |
|     /**
 | |
|      * If we're only provided a single input, we can just make a function
 | |
|      * that returns the output.
 | |
|      */
 | |
|     if (inputLength === 1)
 | |
|         return () => output[0];
 | |
|     // If input runs highest -> lowest, reverse both arrays
 | |
|     if (input[0] > input[inputLength - 1]) {
 | |
|         input = [...input].reverse();
 | |
|         output = [...output].reverse();
 | |
|     }
 | |
|     const mixers = createMixers(output, ease, mixer);
 | |
|     const numMixers = mixers.length;
 | |
|     const interpolator = (v) => {
 | |
|         let i = 0;
 | |
|         if (numMixers > 1) {
 | |
|             for (; i < input.length - 2; i++) {
 | |
|                 if (v < input[i + 1])
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|         const progressInRange = progress(input[i], input[i + 1], v);
 | |
|         return mixers[i](progressInRange);
 | |
|     };
 | |
|     return isClamp
 | |
|         ? (v) => interpolator(clamp(input[0], input[inputLength - 1], v))
 | |
|         : interpolator;
 | |
| }
 | |
| 
 | |
| export { interpolate };
 |