 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>
		
			
				
	
	
		
			362 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const { AtRule, Rule } = require('postcss')
 | |
| let parser = require('postcss-selector-parser')
 | |
| 
 | |
| /**
 | |
|  * Run a selector string through postcss-selector-parser
 | |
|  */
 | |
| function parse(rawSelector, rule) {
 | |
|   let nodes
 | |
|   try {
 | |
|     parser(parsed => {
 | |
|       nodes = parsed
 | |
|     }).processSync(rawSelector)
 | |
|   } catch (e) {
 | |
|     if (rawSelector.includes(':')) {
 | |
|       throw rule ? rule.error('Missed semicolon') : e
 | |
|     } else {
 | |
|       throw rule ? rule.error(e.message) : e
 | |
|     }
 | |
|   }
 | |
|   return nodes.at(0)
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Replaces the "&" token in a node's selector with the parent selector
 | |
|  * similar to what SCSS does.
 | |
|  *
 | |
|  * Mutates the nodes list
 | |
|  */
 | |
| function interpolateAmpInSelector(nodes, parent) {
 | |
|   let replaced = false
 | |
|   nodes.each(node => {
 | |
|     if (node.type === 'nesting') {
 | |
|       let clonedParent = parent.clone({})
 | |
|       if (node.value !== '&') {
 | |
|         node.replaceWith(
 | |
|           parse(node.value.replace('&', clonedParent.toString()))
 | |
|         )
 | |
|       } else {
 | |
|         node.replaceWith(clonedParent)
 | |
|       }
 | |
|       replaced = true
 | |
|     } else if ('nodes' in node && node.nodes) {
 | |
|       if (interpolateAmpInSelector(node, parent)) {
 | |
|         replaced = true
 | |
|       }
 | |
|     }
 | |
|   })
 | |
|   return replaced
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Combines parent and child selectors, in a SCSS-like way
 | |
|  */
 | |
| function mergeSelectors(parent, child) {
 | |
|   let merged = []
 | |
|   parent.selectors.forEach(sel => {
 | |
|     let parentNode = parse(sel, parent)
 | |
| 
 | |
|     child.selectors.forEach(selector => {
 | |
|       if (!selector) {
 | |
|         return
 | |
|       }
 | |
|       let node = parse(selector, child)
 | |
|       let replaced = interpolateAmpInSelector(node, parentNode)
 | |
|       if (!replaced) {
 | |
|         node.prepend(parser.combinator({ value: ' ' }))
 | |
|         node.prepend(parentNode.clone({}))
 | |
|       }
 | |
|       merged.push(node.toString())
 | |
|     })
 | |
|   })
 | |
|   return merged
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Move a child and its preceeding comment(s) to after "after"
 | |
|  */
 | |
| function breakOut(child, after) {
 | |
|   let prev = child.prev()
 | |
|   after.after(child)
 | |
|   while (prev && prev.type === 'comment') {
 | |
|     let nextPrev = prev.prev()
 | |
|     after.after(prev)
 | |
|     prev = nextPrev
 | |
|   }
 | |
|   return child
 | |
| }
 | |
| 
 | |
| function createFnAtruleChilds(bubble) {
 | |
|   return function atruleChilds(rule, atrule, bubbling, mergeSels = bubbling) {
 | |
|     let children = []
 | |
|     atrule.each(child => {
 | |
|       if (child.type === 'rule' && bubbling) {
 | |
|         if (mergeSels) {
 | |
|           child.selectors = mergeSelectors(rule, child)
 | |
|         }
 | |
|       } else if (child.type === 'atrule' && child.nodes) {
 | |
|         if (bubble[child.name]) {
 | |
|           atruleChilds(rule, child, mergeSels)
 | |
|         } else if (atrule[rootRuleMergeSel] !== false) {
 | |
|           children.push(child)
 | |
|         }
 | |
|       } else {
 | |
|         children.push(child)
 | |
|       }
 | |
|     })
 | |
|     if (bubbling) {
 | |
|       if (children.length) {
 | |
|         let clone = rule.clone({ nodes: [] })
 | |
|         for (let child of children) {
 | |
|           clone.append(child)
 | |
|         }
 | |
|         atrule.prepend(clone)
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function pickDeclarations(selector, declarations, after) {
 | |
|   let parent = new Rule({
 | |
|     nodes: [],
 | |
|     selector
 | |
|   })
 | |
|   parent.append(declarations)
 | |
|   after.after(parent)
 | |
|   return parent
 | |
| }
 | |
| 
 | |
| function atruleNames(defaults, custom) {
 | |
|   let list = {}
 | |
|   for (let name of defaults) {
 | |
|     list[name] = true
 | |
|   }
 | |
|   if (custom) {
 | |
|     for (let name of custom) {
 | |
|       list[name.replace(/^@/, '')] = true
 | |
|     }
 | |
|   }
 | |
|   return list
 | |
| }
 | |
| 
 | |
| function parseRootRuleParams(params) {
 | |
|   params = params.trim()
 | |
|   let braceBlock = params.match(/^\((.*)\)$/)
 | |
|   if (!braceBlock) {
 | |
|     return { selector: params, type: 'basic' }
 | |
|   }
 | |
|   let bits = braceBlock[1].match(/^(with(?:out)?):(.+)$/)
 | |
|   if (bits) {
 | |
|     let allowlist = bits[1] === 'with'
 | |
|     let rules = Object.fromEntries(
 | |
|       bits[2]
 | |
|         .trim()
 | |
|         .split(/\s+/)
 | |
|         .map(name => [name, true])
 | |
|     )
 | |
|     if (allowlist && rules.all) {
 | |
|       return { type: 'noop' }
 | |
|     }
 | |
|     let escapes = rule => !!rules[rule]
 | |
|     if (rules.all) {
 | |
|       escapes = () => true
 | |
|     } else if (allowlist) {
 | |
|       escapes = rule => (rule === 'all' ? false : !rules[rule])
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|       escapes,
 | |
|       type: 'withrules'
 | |
|     }
 | |
|   }
 | |
|   // Unrecognized brace block
 | |
|   return { type: 'unknown' }
 | |
| }
 | |
| 
 | |
| function getAncestorRules(leaf) {
 | |
|   let lineage = []
 | |
|   let parent = leaf.parent
 | |
| 
 | |
|   while (parent && parent instanceof AtRule) {
 | |
|     lineage.push(parent)
 | |
|     parent = parent.parent
 | |
|   }
 | |
|   return lineage
 | |
| }
 | |
| 
 | |
| function unwrapRootRule(rule) {
 | |
|   let escapes = rule[rootRuleEscapes]
 | |
| 
 | |
|   if (!escapes) {
 | |
|     rule.after(rule.nodes)
 | |
|   } else {
 | |
|     let nodes = rule.nodes
 | |
| 
 | |
|     let topEscaped
 | |
|     let topEscapedIdx = -1
 | |
|     let breakoutLeaf
 | |
|     let breakoutRoot
 | |
|     let clone
 | |
| 
 | |
|     let lineage = getAncestorRules(rule)
 | |
|     lineage.forEach((parent, i) => {
 | |
|       if (escapes(parent.name)) {
 | |
|         topEscaped = parent
 | |
|         topEscapedIdx = i
 | |
|         breakoutRoot = clone
 | |
|       } else {
 | |
|         let oldClone = clone
 | |
|         clone = parent.clone({ nodes: [] })
 | |
|         oldClone && clone.append(oldClone)
 | |
|         breakoutLeaf = breakoutLeaf || clone
 | |
|       }
 | |
|     })
 | |
| 
 | |
|     if (!topEscaped) {
 | |
|       rule.after(nodes)
 | |
|     } else if (!breakoutRoot) {
 | |
|       topEscaped.after(nodes)
 | |
|     } else {
 | |
|       let leaf = breakoutLeaf
 | |
|       leaf.append(nodes)
 | |
|       topEscaped.after(breakoutRoot)
 | |
|     }
 | |
| 
 | |
|     if (rule.next() && topEscaped) {
 | |
|       let restRoot
 | |
|       lineage.slice(0, topEscapedIdx + 1).forEach((parent, i, arr) => {
 | |
|         let oldRoot = restRoot
 | |
|         restRoot = parent.clone({ nodes: [] })
 | |
|         oldRoot && restRoot.append(oldRoot)
 | |
| 
 | |
|         let nextSibs = []
 | |
|         let _child = arr[i - 1] || rule
 | |
|         let next = _child.next()
 | |
|         while (next) {
 | |
|           nextSibs.push(next)
 | |
|           next = next.next()
 | |
|         }
 | |
|         restRoot.append(nextSibs)
 | |
|       })
 | |
|       restRoot && (breakoutRoot || nodes[nodes.length - 1]).after(restRoot)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   rule.remove()
 | |
| }
 | |
| 
 | |
| const rootRuleMergeSel = Symbol('rootRuleMergeSel')
 | |
| const rootRuleEscapes = Symbol('rootRuleEscapes')
 | |
| 
 | |
| function normalizeRootRule(rule) {
 | |
|   let { params } = rule
 | |
|   let { escapes, selector, type } = parseRootRuleParams(params)
 | |
|   if (type === 'unknown') {
 | |
|     throw rule.error(
 | |
|       `Unknown @${rule.name} parameter ${JSON.stringify(params)}`
 | |
|     )
 | |
|   }
 | |
|   if (type === 'basic' && selector) {
 | |
|     let selectorBlock = new Rule({ nodes: rule.nodes, selector })
 | |
|     rule.removeAll()
 | |
|     rule.append(selectorBlock)
 | |
|   }
 | |
|   rule[rootRuleEscapes] = escapes
 | |
|   rule[rootRuleMergeSel] = escapes ? !escapes('all') : type === 'noop'
 | |
| }
 | |
| 
 | |
| const hasRootRule = Symbol('hasRootRule')
 | |
| 
 | |
| module.exports = (opts = {}) => {
 | |
|   let bubble = atruleNames(
 | |
|     ['media', 'supports', 'layer', 'container', 'starting-style'],
 | |
|     opts.bubble
 | |
|   )
 | |
|   let atruleChilds = createFnAtruleChilds(bubble)
 | |
|   let unwrap = atruleNames(
 | |
|     [
 | |
|       'document',
 | |
|       'font-face',
 | |
|       'keyframes',
 | |
|       '-webkit-keyframes',
 | |
|       '-moz-keyframes'
 | |
|     ],
 | |
|     opts.unwrap
 | |
|   )
 | |
|   let rootRuleName = (opts.rootRuleName || 'at-root').replace(/^@/, '')
 | |
|   let preserveEmpty = opts.preserveEmpty
 | |
| 
 | |
|   return {
 | |
|     Once(root) {
 | |
|       root.walkAtRules(rootRuleName, node => {
 | |
|         normalizeRootRule(node)
 | |
|         root[hasRootRule] = true
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     postcssPlugin: 'postcss-nested',
 | |
| 
 | |
|     RootExit(root) {
 | |
|       if (root[hasRootRule]) {
 | |
|         root.walkAtRules(rootRuleName, unwrapRootRule)
 | |
|         root[hasRootRule] = false
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     Rule(rule) {
 | |
|       let unwrapped = false
 | |
|       let after = rule
 | |
|       let copyDeclarations = false
 | |
|       let declarations = []
 | |
| 
 | |
|       rule.each(child => {
 | |
|         if (child.type === 'rule') {
 | |
|           if (declarations.length) {
 | |
|             after = pickDeclarations(rule.selector, declarations, after)
 | |
|             declarations = []
 | |
|           }
 | |
| 
 | |
|           copyDeclarations = true
 | |
|           unwrapped = true
 | |
|           child.selectors = mergeSelectors(rule, child)
 | |
|           after = breakOut(child, after)
 | |
|         } else if (child.type === 'atrule') {
 | |
|           if (declarations.length) {
 | |
|             after = pickDeclarations(rule.selector, declarations, after)
 | |
|             declarations = []
 | |
|           }
 | |
|           if (child.name === rootRuleName) {
 | |
|             unwrapped = true
 | |
|             atruleChilds(rule, child, true, child[rootRuleMergeSel])
 | |
|             after = breakOut(child, after)
 | |
|           } else if (bubble[child.name]) {
 | |
|             copyDeclarations = true
 | |
|             unwrapped = true
 | |
|             atruleChilds(rule, child, true)
 | |
|             after = breakOut(child, after)
 | |
|           } else if (unwrap[child.name]) {
 | |
|             copyDeclarations = true
 | |
|             unwrapped = true
 | |
|             atruleChilds(rule, child, false)
 | |
|             after = breakOut(child, after)
 | |
|           } else if (copyDeclarations) {
 | |
|             declarations.push(child)
 | |
|           }
 | |
|         } else if (child.type === 'decl' && copyDeclarations) {
 | |
|           declarations.push(child)
 | |
|         }
 | |
|       })
 | |
| 
 | |
|       if (declarations.length) {
 | |
|         after = pickDeclarations(rule.selector, declarations, after)
 | |
|       }
 | |
| 
 | |
|       if (unwrapped && preserveEmpty !== true) {
 | |
|         rule.raws.semicolon = true
 | |
|         if (rule.nodes.length === 0) rule.remove()
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| module.exports.postcss = true
 |