 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>
		
			
				
	
	
		
			264 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| class QuickLRU {
 | |
| 	constructor(options = {}) {
 | |
| 		if (!(options.maxSize && options.maxSize > 0)) {
 | |
| 			throw new TypeError('`maxSize` must be a number greater than 0');
 | |
| 		}
 | |
| 
 | |
| 		if (typeof options.maxAge === 'number' && options.maxAge === 0) {
 | |
| 			throw new TypeError('`maxAge` must be a number greater than 0');
 | |
| 		}
 | |
| 
 | |
| 		this.maxSize = options.maxSize;
 | |
| 		this.maxAge = options.maxAge || Infinity;
 | |
| 		this.onEviction = options.onEviction;
 | |
| 		this.cache = new Map();
 | |
| 		this.oldCache = new Map();
 | |
| 		this._size = 0;
 | |
| 	}
 | |
| 
 | |
| 	_emitEvictions(cache) {
 | |
| 		if (typeof this.onEviction !== 'function') {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		for (const [key, item] of cache) {
 | |
| 			this.onEviction(key, item.value);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	_deleteIfExpired(key, item) {
 | |
| 		if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
 | |
| 			if (typeof this.onEviction === 'function') {
 | |
| 				this.onEviction(key, item.value);
 | |
| 			}
 | |
| 
 | |
| 			return this.delete(key);
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	_getOrDeleteIfExpired(key, item) {
 | |
| 		const deleted = this._deleteIfExpired(key, item);
 | |
| 		if (deleted === false) {
 | |
| 			return item.value;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	_getItemValue(key, item) {
 | |
| 		return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
 | |
| 	}
 | |
| 
 | |
| 	_peek(key, cache) {
 | |
| 		const item = cache.get(key);
 | |
| 
 | |
| 		return this._getItemValue(key, item);
 | |
| 	}
 | |
| 
 | |
| 	_set(key, value) {
 | |
| 		this.cache.set(key, value);
 | |
| 		this._size++;
 | |
| 
 | |
| 		if (this._size >= this.maxSize) {
 | |
| 			this._size = 0;
 | |
| 			this._emitEvictions(this.oldCache);
 | |
| 			this.oldCache = this.cache;
 | |
| 			this.cache = new Map();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	_moveToRecent(key, item) {
 | |
| 		this.oldCache.delete(key);
 | |
| 		this._set(key, item);
 | |
| 	}
 | |
| 
 | |
| 	* _entriesAscending() {
 | |
| 		for (const item of this.oldCache) {
 | |
| 			const [key, value] = item;
 | |
| 			if (!this.cache.has(key)) {
 | |
| 				const deleted = this._deleteIfExpired(key, value);
 | |
| 				if (deleted === false) {
 | |
| 					yield item;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for (const item of this.cache) {
 | |
| 			const [key, value] = item;
 | |
| 			const deleted = this._deleteIfExpired(key, value);
 | |
| 			if (deleted === false) {
 | |
| 				yield item;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	get(key) {
 | |
| 		if (this.cache.has(key)) {
 | |
| 			const item = this.cache.get(key);
 | |
| 
 | |
| 			return this._getItemValue(key, item);
 | |
| 		}
 | |
| 
 | |
| 		if (this.oldCache.has(key)) {
 | |
| 			const item = this.oldCache.get(key);
 | |
| 			if (this._deleteIfExpired(key, item) === false) {
 | |
| 				this._moveToRecent(key, item);
 | |
| 				return item.value;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
 | |
| 		if (this.cache.has(key)) {
 | |
| 			this.cache.set(key, {
 | |
| 				value,
 | |
| 				maxAge
 | |
| 			});
 | |
| 		} else {
 | |
| 			this._set(key, {value, expiry: maxAge});
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	has(key) {
 | |
| 		if (this.cache.has(key)) {
 | |
| 			return !this._deleteIfExpired(key, this.cache.get(key));
 | |
| 		}
 | |
| 
 | |
| 		if (this.oldCache.has(key)) {
 | |
| 			return !this._deleteIfExpired(key, this.oldCache.get(key));
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	peek(key) {
 | |
| 		if (this.cache.has(key)) {
 | |
| 			return this._peek(key, this.cache);
 | |
| 		}
 | |
| 
 | |
| 		if (this.oldCache.has(key)) {
 | |
| 			return this._peek(key, this.oldCache);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	delete(key) {
 | |
| 		const deleted = this.cache.delete(key);
 | |
| 		if (deleted) {
 | |
| 			this._size--;
 | |
| 		}
 | |
| 
 | |
| 		return this.oldCache.delete(key) || deleted;
 | |
| 	}
 | |
| 
 | |
| 	clear() {
 | |
| 		this.cache.clear();
 | |
| 		this.oldCache.clear();
 | |
| 		this._size = 0;
 | |
| 	}
 | |
| 	
 | |
| 	resize(newSize) {
 | |
| 		if (!(newSize && newSize > 0)) {
 | |
| 			throw new TypeError('`maxSize` must be a number greater than 0');
 | |
| 		}
 | |
| 
 | |
| 		const items = [...this._entriesAscending()];
 | |
| 		const removeCount = items.length - newSize;
 | |
| 		if (removeCount < 0) {
 | |
| 			this.cache = new Map(items);
 | |
| 			this.oldCache = new Map();
 | |
| 			this._size = items.length;
 | |
| 		} else {
 | |
| 			if (removeCount > 0) {
 | |
| 				this._emitEvictions(items.slice(0, removeCount));
 | |
| 			}
 | |
| 
 | |
| 			this.oldCache = new Map(items.slice(removeCount));
 | |
| 			this.cache = new Map();
 | |
| 			this._size = 0;
 | |
| 		}
 | |
| 
 | |
| 		this.maxSize = newSize;
 | |
| 	}
 | |
| 
 | |
| 	* keys() {
 | |
| 		for (const [key] of this) {
 | |
| 			yield key;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	* values() {
 | |
| 		for (const [, value] of this) {
 | |
| 			yield value;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	* [Symbol.iterator]() {
 | |
| 		for (const item of this.cache) {
 | |
| 			const [key, value] = item;
 | |
| 			const deleted = this._deleteIfExpired(key, value);
 | |
| 			if (deleted === false) {
 | |
| 				yield [key, value.value];
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for (const item of this.oldCache) {
 | |
| 			const [key, value] = item;
 | |
| 			if (!this.cache.has(key)) {
 | |
| 				const deleted = this._deleteIfExpired(key, value);
 | |
| 				if (deleted === false) {
 | |
| 					yield [key, value.value];
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	* entriesDescending() {
 | |
| 		let items = [...this.cache];
 | |
| 		for (let i = items.length - 1; i >= 0; --i) {
 | |
| 			const item = items[i];
 | |
| 			const [key, value] = item;
 | |
| 			const deleted = this._deleteIfExpired(key, value);
 | |
| 			if (deleted === false) {
 | |
| 				yield [key, value.value];
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		items = [...this.oldCache];
 | |
| 		for (let i = items.length - 1; i >= 0; --i) {
 | |
| 			const item = items[i];
 | |
| 			const [key, value] = item;
 | |
| 			if (!this.cache.has(key)) {
 | |
| 				const deleted = this._deleteIfExpired(key, value);
 | |
| 				if (deleted === false) {
 | |
| 					yield [key, value.value];
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	* entriesAscending() {
 | |
| 		for (const [key, value] of this._entriesAscending()) {
 | |
| 			yield [key, value.value];
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	get size() {
 | |
| 		if (!this._size) {
 | |
| 			return this.oldCache.size;
 | |
| 		}
 | |
| 
 | |
| 		let oldCacheSize = 0;
 | |
| 		for (const key of this.oldCache.keys()) {
 | |
| 			if (!this.cache.has(key)) {
 | |
| 				oldCacheSize++;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return Math.min(this._size + oldCacheSize, this.maxSize);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| module.exports = QuickLRU;
 |