 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>
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict'
 | |
| 
 | |
| const ANY = Symbol('SemVer ANY')
 | |
| // hoisted class for cyclic dependency
 | |
| class Comparator {
 | |
|   static get ANY () {
 | |
|     return ANY
 | |
|   }
 | |
| 
 | |
|   constructor (comp, options) {
 | |
|     options = parseOptions(options)
 | |
| 
 | |
|     if (comp instanceof Comparator) {
 | |
|       if (comp.loose === !!options.loose) {
 | |
|         return comp
 | |
|       } else {
 | |
|         comp = comp.value
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     comp = comp.trim().split(/\s+/).join(' ')
 | |
|     debug('comparator', comp, options)
 | |
|     this.options = options
 | |
|     this.loose = !!options.loose
 | |
|     this.parse(comp)
 | |
| 
 | |
|     if (this.semver === ANY) {
 | |
|       this.value = ''
 | |
|     } else {
 | |
|       this.value = this.operator + this.semver.version
 | |
|     }
 | |
| 
 | |
|     debug('comp', this)
 | |
|   }
 | |
| 
 | |
|   parse (comp) {
 | |
|     const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
 | |
|     const m = comp.match(r)
 | |
| 
 | |
|     if (!m) {
 | |
|       throw new TypeError(`Invalid comparator: ${comp}`)
 | |
|     }
 | |
| 
 | |
|     this.operator = m[1] !== undefined ? m[1] : ''
 | |
|     if (this.operator === '=') {
 | |
|       this.operator = ''
 | |
|     }
 | |
| 
 | |
|     // if it literally is just '>' or '' then allow anything.
 | |
|     if (!m[2]) {
 | |
|       this.semver = ANY
 | |
|     } else {
 | |
|       this.semver = new SemVer(m[2], this.options.loose)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   toString () {
 | |
|     return this.value
 | |
|   }
 | |
| 
 | |
|   test (version) {
 | |
|     debug('Comparator.test', version, this.options.loose)
 | |
| 
 | |
|     if (this.semver === ANY || version === ANY) {
 | |
|       return true
 | |
|     }
 | |
| 
 | |
|     if (typeof version === 'string') {
 | |
|       try {
 | |
|         version = new SemVer(version, this.options)
 | |
|       } catch (er) {
 | |
|         return false
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return cmp(version, this.operator, this.semver, this.options)
 | |
|   }
 | |
| 
 | |
|   intersects (comp, options) {
 | |
|     if (!(comp instanceof Comparator)) {
 | |
|       throw new TypeError('a Comparator is required')
 | |
|     }
 | |
| 
 | |
|     if (this.operator === '') {
 | |
|       if (this.value === '') {
 | |
|         return true
 | |
|       }
 | |
|       return new Range(comp.value, options).test(this.value)
 | |
|     } else if (comp.operator === '') {
 | |
|       if (comp.value === '') {
 | |
|         return true
 | |
|       }
 | |
|       return new Range(this.value, options).test(comp.semver)
 | |
|     }
 | |
| 
 | |
|     options = parseOptions(options)
 | |
| 
 | |
|     // Special cases where nothing can possibly be lower
 | |
|     if (options.includePrerelease &&
 | |
|       (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
 | |
|       return false
 | |
|     }
 | |
|     if (!options.includePrerelease &&
 | |
|       (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
 | |
|       return false
 | |
|     }
 | |
| 
 | |
|     // Same direction increasing (> or >=)
 | |
|     if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
 | |
|       return true
 | |
|     }
 | |
|     // Same direction decreasing (< or <=)
 | |
|     if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
 | |
|       return true
 | |
|     }
 | |
|     // same SemVer and both sides are inclusive (<= or >=)
 | |
|     if (
 | |
|       (this.semver.version === comp.semver.version) &&
 | |
|       this.operator.includes('=') && comp.operator.includes('=')) {
 | |
|       return true
 | |
|     }
 | |
|     // opposite directions less than
 | |
|     if (cmp(this.semver, '<', comp.semver, options) &&
 | |
|       this.operator.startsWith('>') && comp.operator.startsWith('<')) {
 | |
|       return true
 | |
|     }
 | |
|     // opposite directions greater than
 | |
|     if (cmp(this.semver, '>', comp.semver, options) &&
 | |
|       this.operator.startsWith('<') && comp.operator.startsWith('>')) {
 | |
|       return true
 | |
|     }
 | |
|     return false
 | |
|   }
 | |
| }
 | |
| 
 | |
| module.exports = Comparator
 | |
| 
 | |
| const parseOptions = require('../internal/parse-options')
 | |
| const { safeRe: re, t } = require('../internal/re')
 | |
| const cmp = require('../functions/cmp')
 | |
| const debug = require('../internal/debug')
 | |
| const SemVer = require('./semver')
 | |
| const Range = require('./range')
 |