 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>
		
			
				
	
	
		
			338 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { SubscriptionManager } from '../utils/subscription-manager.mjs';
 | |
| import { velocityPerSecond } from '../utils/velocity-per-second.mjs';
 | |
| import { warnOnce } from '../utils/warn-once.mjs';
 | |
| import { frame, frameData } from '../frameloop/frame.mjs';
 | |
| 
 | |
| const isFloat = (value) => {
 | |
|     return !isNaN(parseFloat(value));
 | |
| };
 | |
| const collectMotionValues = {
 | |
|     current: undefined,
 | |
| };
 | |
| /**
 | |
|  * `MotionValue` is used to track the state and velocity of motion values.
 | |
|  *
 | |
|  * @public
 | |
|  */
 | |
| class MotionValue {
 | |
|     /**
 | |
|      * @param init - The initiating value
 | |
|      * @param config - Optional configuration options
 | |
|      *
 | |
|      * -  `transformer`: A function to transform incoming values with.
 | |
|      *
 | |
|      * @internal
 | |
|      */
 | |
|     constructor(init, options = {}) {
 | |
|         /**
 | |
|          * This will be replaced by the build step with the latest version number.
 | |
|          * When MotionValues are provided to motion components, warn if versions are mixed.
 | |
|          */
 | |
|         this.version = "10.18.0";
 | |
|         /**
 | |
|          * Duration, in milliseconds, since last updating frame.
 | |
|          *
 | |
|          * @internal
 | |
|          */
 | |
|         this.timeDelta = 0;
 | |
|         /**
 | |
|          * Timestamp of the last time this `MotionValue` was updated.
 | |
|          *
 | |
|          * @internal
 | |
|          */
 | |
|         this.lastUpdated = 0;
 | |
|         /**
 | |
|          * Tracks whether this value can output a velocity. Currently this is only true
 | |
|          * if the value is numerical, but we might be able to widen the scope here and support
 | |
|          * other value types.
 | |
|          *
 | |
|          * @internal
 | |
|          */
 | |
|         this.canTrackVelocity = false;
 | |
|         /**
 | |
|          * An object containing a SubscriptionManager for each active event.
 | |
|          */
 | |
|         this.events = {};
 | |
|         this.updateAndNotify = (v, render = true) => {
 | |
|             this.prev = this.current;
 | |
|             this.current = v;
 | |
|             // Update timestamp
 | |
|             const { delta, timestamp } = frameData;
 | |
|             if (this.lastUpdated !== timestamp) {
 | |
|                 this.timeDelta = delta;
 | |
|                 this.lastUpdated = timestamp;
 | |
|                 frame.postRender(this.scheduleVelocityCheck);
 | |
|             }
 | |
|             // Update update subscribers
 | |
|             if (this.prev !== this.current && this.events.change) {
 | |
|                 this.events.change.notify(this.current);
 | |
|             }
 | |
|             // Update velocity subscribers
 | |
|             if (this.events.velocityChange) {
 | |
|                 this.events.velocityChange.notify(this.getVelocity());
 | |
|             }
 | |
|             // Update render subscribers
 | |
|             if (render && this.events.renderRequest) {
 | |
|                 this.events.renderRequest.notify(this.current);
 | |
|             }
 | |
|         };
 | |
|         /**
 | |
|          * Schedule a velocity check for the next frame.
 | |
|          *
 | |
|          * This is an instanced and bound function to prevent generating a new
 | |
|          * function once per frame.
 | |
|          *
 | |
|          * @internal
 | |
|          */
 | |
|         this.scheduleVelocityCheck = () => frame.postRender(this.velocityCheck);
 | |
|         /**
 | |
|          * Updates `prev` with `current` if the value hasn't been updated this frame.
 | |
|          * This ensures velocity calculations return `0`.
 | |
|          *
 | |
|          * This is an instanced and bound function to prevent generating a new
 | |
|          * function once per frame.
 | |
|          *
 | |
|          * @internal
 | |
|          */
 | |
|         this.velocityCheck = ({ timestamp }) => {
 | |
|             if (timestamp !== this.lastUpdated) {
 | |
|                 this.prev = this.current;
 | |
|                 if (this.events.velocityChange) {
 | |
|                     this.events.velocityChange.notify(this.getVelocity());
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|         this.hasAnimated = false;
 | |
|         this.prev = this.current = init;
 | |
|         this.canTrackVelocity = isFloat(this.current);
 | |
|         this.owner = options.owner;
 | |
|     }
 | |
|     /**
 | |
|      * Adds a function that will be notified when the `MotionValue` is updated.
 | |
|      *
 | |
|      * It returns a function that, when called, will cancel the subscription.
 | |
|      *
 | |
|      * When calling `onChange` inside a React component, it should be wrapped with the
 | |
|      * `useEffect` hook. As it returns an unsubscribe function, this should be returned
 | |
|      * from the `useEffect` function to ensure you don't add duplicate subscribers..
 | |
|      *
 | |
|      * ```jsx
 | |
|      * export const MyComponent = () => {
 | |
|      *   const x = useMotionValue(0)
 | |
|      *   const y = useMotionValue(0)
 | |
|      *   const opacity = useMotionValue(1)
 | |
|      *
 | |
|      *   useEffect(() => {
 | |
|      *     function updateOpacity() {
 | |
|      *       const maxXY = Math.max(x.get(), y.get())
 | |
|      *       const newOpacity = transform(maxXY, [0, 100], [1, 0])
 | |
|      *       opacity.set(newOpacity)
 | |
|      *     }
 | |
|      *
 | |
|      *     const unsubscribeX = x.on("change", updateOpacity)
 | |
|      *     const unsubscribeY = y.on("change", updateOpacity)
 | |
|      *
 | |
|      *     return () => {
 | |
|      *       unsubscribeX()
 | |
|      *       unsubscribeY()
 | |
|      *     }
 | |
|      *   }, [])
 | |
|      *
 | |
|      *   return <motion.div style={{ x }} />
 | |
|      * }
 | |
|      * ```
 | |
|      *
 | |
|      * @param subscriber - A function that receives the latest value.
 | |
|      * @returns A function that, when called, will cancel this subscription.
 | |
|      *
 | |
|      * @deprecated
 | |
|      */
 | |
|     onChange(subscription) {
 | |
|         if (process.env.NODE_ENV !== "production") {
 | |
|             warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
 | |
|         }
 | |
|         return this.on("change", subscription);
 | |
|     }
 | |
|     on(eventName, callback) {
 | |
|         if (!this.events[eventName]) {
 | |
|             this.events[eventName] = new SubscriptionManager();
 | |
|         }
 | |
|         const unsubscribe = this.events[eventName].add(callback);
 | |
|         if (eventName === "change") {
 | |
|             return () => {
 | |
|                 unsubscribe();
 | |
|                 /**
 | |
|                  * If we have no more change listeners by the start
 | |
|                  * of the next frame, stop active animations.
 | |
|                  */
 | |
|                 frame.read(() => {
 | |
|                     if (!this.events.change.getSize()) {
 | |
|                         this.stop();
 | |
|                     }
 | |
|                 });
 | |
|             };
 | |
|         }
 | |
|         return unsubscribe;
 | |
|     }
 | |
|     clearListeners() {
 | |
|         for (const eventManagers in this.events) {
 | |
|             this.events[eventManagers].clear();
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|      * Attaches a passive effect to the `MotionValue`.
 | |
|      *
 | |
|      * @internal
 | |
|      */
 | |
|     attach(passiveEffect, stopPassiveEffect) {
 | |
|         this.passiveEffect = passiveEffect;
 | |
|         this.stopPassiveEffect = stopPassiveEffect;
 | |
|     }
 | |
|     /**
 | |
|      * Sets the state of the `MotionValue`.
 | |
|      *
 | |
|      * @remarks
 | |
|      *
 | |
|      * ```jsx
 | |
|      * const x = useMotionValue(0)
 | |
|      * x.set(10)
 | |
|      * ```
 | |
|      *
 | |
|      * @param latest - Latest value to set.
 | |
|      * @param render - Whether to notify render subscribers. Defaults to `true`
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     set(v, render = true) {
 | |
|         if (!render || !this.passiveEffect) {
 | |
|             this.updateAndNotify(v, render);
 | |
|         }
 | |
|         else {
 | |
|             this.passiveEffect(v, this.updateAndNotify);
 | |
|         }
 | |
|     }
 | |
|     setWithVelocity(prev, current, delta) {
 | |
|         this.set(current);
 | |
|         this.prev = prev;
 | |
|         this.timeDelta = delta;
 | |
|     }
 | |
|     /**
 | |
|      * Set the state of the `MotionValue`, stopping any active animations,
 | |
|      * effects, and resets velocity to `0`.
 | |
|      */
 | |
|     jump(v) {
 | |
|         this.updateAndNotify(v);
 | |
|         this.prev = v;
 | |
|         this.stop();
 | |
|         if (this.stopPassiveEffect)
 | |
|             this.stopPassiveEffect();
 | |
|     }
 | |
|     /**
 | |
|      * Returns the latest state of `MotionValue`
 | |
|      *
 | |
|      * @returns - The latest state of `MotionValue`
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     get() {
 | |
|         if (collectMotionValues.current) {
 | |
|             collectMotionValues.current.push(this);
 | |
|         }
 | |
|         return this.current;
 | |
|     }
 | |
|     /**
 | |
|      * @public
 | |
|      */
 | |
|     getPrevious() {
 | |
|         return this.prev;
 | |
|     }
 | |
|     /**
 | |
|      * Returns the latest velocity of `MotionValue`
 | |
|      *
 | |
|      * @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     getVelocity() {
 | |
|         // This could be isFloat(this.prev) && isFloat(this.current), but that would be wasteful
 | |
|         return this.canTrackVelocity
 | |
|             ? // These casts could be avoided if parseFloat would be typed better
 | |
|                 velocityPerSecond(parseFloat(this.current) -
 | |
|                     parseFloat(this.prev), this.timeDelta)
 | |
|             : 0;
 | |
|     }
 | |
|     /**
 | |
|      * Registers a new animation to control this `MotionValue`. Only one
 | |
|      * animation can drive a `MotionValue` at one time.
 | |
|      *
 | |
|      * ```jsx
 | |
|      * value.start()
 | |
|      * ```
 | |
|      *
 | |
|      * @param animation - A function that starts the provided animation
 | |
|      *
 | |
|      * @internal
 | |
|      */
 | |
|     start(startAnimation) {
 | |
|         this.stop();
 | |
|         return new Promise((resolve) => {
 | |
|             this.hasAnimated = true;
 | |
|             this.animation = startAnimation(resolve);
 | |
|             if (this.events.animationStart) {
 | |
|                 this.events.animationStart.notify();
 | |
|             }
 | |
|         }).then(() => {
 | |
|             if (this.events.animationComplete) {
 | |
|                 this.events.animationComplete.notify();
 | |
|             }
 | |
|             this.clearAnimation();
 | |
|         });
 | |
|     }
 | |
|     /**
 | |
|      * Stop the currently active animation.
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     stop() {
 | |
|         if (this.animation) {
 | |
|             this.animation.stop();
 | |
|             if (this.events.animationCancel) {
 | |
|                 this.events.animationCancel.notify();
 | |
|             }
 | |
|         }
 | |
|         this.clearAnimation();
 | |
|     }
 | |
|     /**
 | |
|      * Returns `true` if this value is currently animating.
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     isAnimating() {
 | |
|         return !!this.animation;
 | |
|     }
 | |
|     clearAnimation() {
 | |
|         delete this.animation;
 | |
|     }
 | |
|     /**
 | |
|      * Destroy and clean up subscribers to this `MotionValue`.
 | |
|      *
 | |
|      * The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically
 | |
|      * handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually
 | |
|      * created a `MotionValue` via the `motionValue` function.
 | |
|      *
 | |
|      * @public
 | |
|      */
 | |
|     destroy() {
 | |
|         this.clearListeners();
 | |
|         this.stop();
 | |
|         if (this.stopPassiveEffect) {
 | |
|             this.stopPassiveEffect();
 | |
|         }
 | |
|     }
 | |
| }
 | |
| function motionValue(init, options) {
 | |
|     return new MotionValue(init, options);
 | |
| }
 | |
| 
 | |
| export { MotionValue, collectMotionValues, motionValue };
 |