 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>
		
			
				
	
	
		
			517 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			517 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * @fileoverview Validates JSDoc comments are syntactically correct
 | |
|  * @author Nicholas C. Zakas
 | |
|  * @deprecated in ESLint v5.10.0
 | |
|  */
 | |
| "use strict";
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Requirements
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| const doctrine = require("doctrine");
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Rule Definition
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| /** @type {import('../shared/types').Rule} */
 | |
| module.exports = {
 | |
|     meta: {
 | |
|         type: "suggestion",
 | |
| 
 | |
|         docs: {
 | |
|             description: "Enforce valid JSDoc comments",
 | |
|             recommended: false,
 | |
|             url: "https://eslint.org/docs/latest/rules/valid-jsdoc"
 | |
|         },
 | |
| 
 | |
|         schema: [
 | |
|             {
 | |
|                 type: "object",
 | |
|                 properties: {
 | |
|                     prefer: {
 | |
|                         type: "object",
 | |
|                         additionalProperties: {
 | |
|                             type: "string"
 | |
|                         }
 | |
|                     },
 | |
|                     preferType: {
 | |
|                         type: "object",
 | |
|                         additionalProperties: {
 | |
|                             type: "string"
 | |
|                         }
 | |
|                     },
 | |
|                     requireReturn: {
 | |
|                         type: "boolean",
 | |
|                         default: true
 | |
|                     },
 | |
|                     requireParamDescription: {
 | |
|                         type: "boolean",
 | |
|                         default: true
 | |
|                     },
 | |
|                     requireReturnDescription: {
 | |
|                         type: "boolean",
 | |
|                         default: true
 | |
|                     },
 | |
|                     matchDescription: {
 | |
|                         type: "string"
 | |
|                     },
 | |
|                     requireReturnType: {
 | |
|                         type: "boolean",
 | |
|                         default: true
 | |
|                     },
 | |
|                     requireParamType: {
 | |
|                         type: "boolean",
 | |
|                         default: true
 | |
|                     }
 | |
|                 },
 | |
|                 additionalProperties: false
 | |
|             }
 | |
|         ],
 | |
| 
 | |
|         fixable: "code",
 | |
|         messages: {
 | |
|             unexpectedTag: "Unexpected @{{title}} tag; function has no return statement.",
 | |
|             expected: "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.",
 | |
|             use: "Use @{{name}} instead.",
 | |
|             useType: "Use '{{expectedTypeName}}' instead of '{{currentTypeName}}'.",
 | |
|             syntaxError: "JSDoc syntax error.",
 | |
|             missingBrace: "JSDoc type missing brace.",
 | |
|             missingParamDesc: "Missing JSDoc parameter description for '{{name}}'.",
 | |
|             missingParamType: "Missing JSDoc parameter type for '{{name}}'.",
 | |
|             missingReturnType: "Missing JSDoc return type.",
 | |
|             missingReturnDesc: "Missing JSDoc return description.",
 | |
|             missingReturn: "Missing JSDoc @{{returns}} for function.",
 | |
|             missingParam: "Missing JSDoc for parameter '{{name}}'.",
 | |
|             duplicateParam: "Duplicate JSDoc parameter '{{name}}'.",
 | |
|             unsatisfiedDesc: "JSDoc description does not satisfy the regex pattern."
 | |
|         },
 | |
| 
 | |
|         deprecated: true,
 | |
|         replacedBy: []
 | |
|     },
 | |
| 
 | |
|     create(context) {
 | |
| 
 | |
|         const options = context.options[0] || {},
 | |
|             prefer = options.prefer || {},
 | |
|             sourceCode = context.sourceCode,
 | |
| 
 | |
|             // these both default to true, so you have to explicitly make them false
 | |
|             requireReturn = options.requireReturn !== false,
 | |
|             requireParamDescription = options.requireParamDescription !== false,
 | |
|             requireReturnDescription = options.requireReturnDescription !== false,
 | |
|             requireReturnType = options.requireReturnType !== false,
 | |
|             requireParamType = options.requireParamType !== false,
 | |
|             preferType = options.preferType || {},
 | |
|             checkPreferType = Object.keys(preferType).length !== 0;
 | |
| 
 | |
|         //--------------------------------------------------------------------------
 | |
|         // Helpers
 | |
|         //--------------------------------------------------------------------------
 | |
| 
 | |
|         // Using a stack to store if a function returns or not (handling nested functions)
 | |
|         const fns = [];
 | |
| 
 | |
|         /**
 | |
|          * Check if node type is a Class
 | |
|          * @param {ASTNode} node node to check.
 | |
|          * @returns {boolean} True is its a class
 | |
|          * @private
 | |
|          */
 | |
|         function isTypeClass(node) {
 | |
|             return node.type === "ClassExpression" || node.type === "ClassDeclaration";
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * When parsing a new function, store it in our function stack.
 | |
|          * @param {ASTNode} node A function node to check.
 | |
|          * @returns {void}
 | |
|          * @private
 | |
|          */
 | |
|         function startFunction(node) {
 | |
|             fns.push({
 | |
|                 returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") ||
 | |
|                     isTypeClass(node) || node.async
 | |
|             });
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Indicate that return has been found in the current function.
 | |
|          * @param {ASTNode} node The return node.
 | |
|          * @returns {void}
 | |
|          * @private
 | |
|          */
 | |
|         function addReturn(node) {
 | |
|             const functionState = fns[fns.length - 1];
 | |
| 
 | |
|             if (functionState && node.argument !== null) {
 | |
|                 functionState.returnPresent = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Check if return tag type is void or undefined
 | |
|          * @param {Object} tag JSDoc tag
 | |
|          * @returns {boolean} True if its of type void or undefined
 | |
|          * @private
 | |
|          */
 | |
|         function isValidReturnType(tag) {
 | |
|             return tag.type === null || tag.type.name === "void" || tag.type.type === "UndefinedLiteral";
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Check if type should be validated based on some exceptions
 | |
|          * @param {Object} type JSDoc tag
 | |
|          * @returns {boolean} True if it can be validated
 | |
|          * @private
 | |
|          */
 | |
|         function canTypeBeValidated(type) {
 | |
|             return type !== "UndefinedLiteral" && // {undefined} as there is no name property available.
 | |
|                    type !== "NullLiteral" && // {null}
 | |
|                    type !== "NullableLiteral" && // {?}
 | |
|                    type !== "FunctionType" && // {function(a)}
 | |
|                    type !== "AllLiteral"; // {*}
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Extract the current and expected type based on the input type object
 | |
|          * @param {Object} type JSDoc tag
 | |
|          * @returns {{currentType: Doctrine.Type, expectedTypeName: string}} The current type annotation and
 | |
|          * the expected name of the annotation
 | |
|          * @private
 | |
|          */
 | |
|         function getCurrentExpectedTypes(type) {
 | |
|             let currentType;
 | |
| 
 | |
|             if (type.name) {
 | |
|                 currentType = type;
 | |
|             } else if (type.expression) {
 | |
|                 currentType = type.expression;
 | |
|             }
 | |
| 
 | |
|             return {
 | |
|                 currentType,
 | |
|                 expectedTypeName: currentType && preferType[currentType.name]
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Gets the location of a JSDoc node in a file
 | |
|          * @param {Token} jsdocComment The comment that this node is parsed from
 | |
|          * @param {{range: number[]}} parsedJsdocNode A tag or other node which was parsed from this comment
 | |
|          * @returns {{start: SourceLocation, end: SourceLocation}} The 0-based source location for the tag
 | |
|          */
 | |
|         function getAbsoluteRange(jsdocComment, parsedJsdocNode) {
 | |
|             return {
 | |
|                 start: sourceCode.getLocFromIndex(jsdocComment.range[0] + 2 + parsedJsdocNode.range[0]),
 | |
|                 end: sourceCode.getLocFromIndex(jsdocComment.range[0] + 2 + parsedJsdocNode.range[1])
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Validate type for a given JSDoc node
 | |
|          * @param {Object} jsdocNode JSDoc node
 | |
|          * @param {Object} type JSDoc tag
 | |
|          * @returns {void}
 | |
|          * @private
 | |
|          */
 | |
|         function validateType(jsdocNode, type) {
 | |
|             if (!type || !canTypeBeValidated(type.type)) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             const typesToCheck = [];
 | |
|             let elements = [];
 | |
| 
 | |
|             switch (type.type) {
 | |
|                 case "TypeApplication": // {Array.<String>}
 | |
|                     elements = type.applications[0].type === "UnionType" ? type.applications[0].elements : type.applications;
 | |
|                     typesToCheck.push(getCurrentExpectedTypes(type));
 | |
|                     break;
 | |
|                 case "RecordType": // {{20:String}}
 | |
|                     elements = type.fields;
 | |
|                     break;
 | |
|                 case "UnionType": // {String|number|Test}
 | |
|                 case "ArrayType": // {[String, number, Test]}
 | |
|                     elements = type.elements;
 | |
|                     break;
 | |
|                 case "FieldType": // Array.<{count: number, votes: number}>
 | |
|                     if (type.value) {
 | |
|                         typesToCheck.push(getCurrentExpectedTypes(type.value));
 | |
|                     }
 | |
|                     break;
 | |
|                 default:
 | |
|                     typesToCheck.push(getCurrentExpectedTypes(type));
 | |
|             }
 | |
| 
 | |
|             elements.forEach(validateType.bind(null, jsdocNode));
 | |
| 
 | |
|             typesToCheck.forEach(typeToCheck => {
 | |
|                 if (typeToCheck.expectedTypeName &&
 | |
|                     typeToCheck.expectedTypeName !== typeToCheck.currentType.name) {
 | |
|                     context.report({
 | |
|                         node: jsdocNode,
 | |
|                         messageId: "useType",
 | |
|                         loc: getAbsoluteRange(jsdocNode, typeToCheck.currentType),
 | |
|                         data: {
 | |
|                             currentTypeName: typeToCheck.currentType.name,
 | |
|                             expectedTypeName: typeToCheck.expectedTypeName
 | |
|                         },
 | |
|                         fix(fixer) {
 | |
|                             return fixer.replaceTextRange(
 | |
|                                 typeToCheck.currentType.range.map(indexInComment => jsdocNode.range[0] + 2 + indexInComment),
 | |
|                                 typeToCheck.expectedTypeName
 | |
|                             );
 | |
|                         }
 | |
|                     });
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Validate the JSDoc node and output warnings if anything is wrong.
 | |
|          * @param {ASTNode} node The AST node to check.
 | |
|          * @returns {void}
 | |
|          * @private
 | |
|          */
 | |
|         function checkJSDoc(node) {
 | |
|             const jsdocNode = sourceCode.getJSDocComment(node),
 | |
|                 functionData = fns.pop(),
 | |
|                 paramTagsByName = Object.create(null),
 | |
|                 paramTags = [];
 | |
|             let hasReturns = false,
 | |
|                 returnsTag,
 | |
|                 hasConstructor = false,
 | |
|                 isInterface = false,
 | |
|                 isOverride = false,
 | |
|                 isAbstract = false;
 | |
| 
 | |
|             // make sure only to validate JSDoc comments
 | |
|             if (jsdocNode) {
 | |
|                 let jsdoc;
 | |
| 
 | |
|                 try {
 | |
|                     jsdoc = doctrine.parse(jsdocNode.value, {
 | |
|                         strict: true,
 | |
|                         unwrap: true,
 | |
|                         sloppy: true,
 | |
|                         range: true
 | |
|                     });
 | |
|                 } catch (ex) {
 | |
| 
 | |
|                     if (/braces/iu.test(ex.message)) {
 | |
|                         context.report({ node: jsdocNode, messageId: "missingBrace" });
 | |
|                     } else {
 | |
|                         context.report({ node: jsdocNode, messageId: "syntaxError" });
 | |
|                     }
 | |
| 
 | |
|                     return;
 | |
|                 }
 | |
| 
 | |
|                 jsdoc.tags.forEach(tag => {
 | |
| 
 | |
|                     switch (tag.title.toLowerCase()) {
 | |
| 
 | |
|                         case "param":
 | |
|                         case "arg":
 | |
|                         case "argument":
 | |
|                             paramTags.push(tag);
 | |
|                             break;
 | |
| 
 | |
|                         case "return":
 | |
|                         case "returns":
 | |
|                             hasReturns = true;
 | |
|                             returnsTag = tag;
 | |
|                             break;
 | |
| 
 | |
|                         case "constructor":
 | |
|                         case "class":
 | |
|                             hasConstructor = true;
 | |
|                             break;
 | |
| 
 | |
|                         case "override":
 | |
|                         case "inheritdoc":
 | |
|                             isOverride = true;
 | |
|                             break;
 | |
| 
 | |
|                         case "abstract":
 | |
|                         case "virtual":
 | |
|                             isAbstract = true;
 | |
|                             break;
 | |
| 
 | |
|                         case "interface":
 | |
|                             isInterface = true;
 | |
|                             break;
 | |
| 
 | |
|                         // no default
 | |
|                     }
 | |
| 
 | |
|                     // check tag preferences
 | |
|                     if (Object.prototype.hasOwnProperty.call(prefer, tag.title) && tag.title !== prefer[tag.title]) {
 | |
|                         const entireTagRange = getAbsoluteRange(jsdocNode, tag);
 | |
| 
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "use",
 | |
|                             loc: {
 | |
|                                 start: entireTagRange.start,
 | |
|                                 end: {
 | |
|                                     line: entireTagRange.start.line,
 | |
|                                     column: entireTagRange.start.column + `@${tag.title}`.length
 | |
|                                 }
 | |
|                             },
 | |
|                             data: { name: prefer[tag.title] },
 | |
|                             fix(fixer) {
 | |
|                                 return fixer.replaceTextRange(
 | |
|                                     [
 | |
|                                         jsdocNode.range[0] + tag.range[0] + 3,
 | |
|                                         jsdocNode.range[0] + tag.range[0] + tag.title.length + 3
 | |
|                                     ],
 | |
|                                     prefer[tag.title]
 | |
|                                 );
 | |
|                             }
 | |
|                         });
 | |
|                     }
 | |
| 
 | |
|                     // validate the types
 | |
|                     if (checkPreferType && tag.type) {
 | |
|                         validateType(jsdocNode, tag.type);
 | |
|                     }
 | |
|                 });
 | |
| 
 | |
|                 paramTags.forEach(param => {
 | |
|                     if (requireParamType && !param.type) {
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "missingParamType",
 | |
|                             loc: getAbsoluteRange(jsdocNode, param),
 | |
|                             data: { name: param.name }
 | |
|                         });
 | |
|                     }
 | |
|                     if (!param.description && requireParamDescription) {
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "missingParamDesc",
 | |
|                             loc: getAbsoluteRange(jsdocNode, param),
 | |
|                             data: { name: param.name }
 | |
|                         });
 | |
|                     }
 | |
|                     if (paramTagsByName[param.name]) {
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "duplicateParam",
 | |
|                             loc: getAbsoluteRange(jsdocNode, param),
 | |
|                             data: { name: param.name }
 | |
|                         });
 | |
|                     } else if (!param.name.includes(".")) {
 | |
|                         paramTagsByName[param.name] = param;
 | |
|                     }
 | |
|                 });
 | |
| 
 | |
|                 if (hasReturns) {
 | |
|                     if (!requireReturn && !functionData.returnPresent && (returnsTag.type === null || !isValidReturnType(returnsTag)) && !isAbstract) {
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "unexpectedTag",
 | |
|                             loc: getAbsoluteRange(jsdocNode, returnsTag),
 | |
|                             data: {
 | |
|                                 title: returnsTag.title
 | |
|                             }
 | |
|                         });
 | |
|                     } else {
 | |
|                         if (requireReturnType && !returnsTag.type) {
 | |
|                             context.report({ node: jsdocNode, messageId: "missingReturnType" });
 | |
|                         }
 | |
| 
 | |
|                         if (!isValidReturnType(returnsTag) && !returnsTag.description && requireReturnDescription) {
 | |
|                             context.report({ node: jsdocNode, messageId: "missingReturnDesc" });
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // check for functions missing @returns
 | |
|                 if (!isOverride && !hasReturns && !hasConstructor && !isInterface &&
 | |
|                     node.parent.kind !== "get" && node.parent.kind !== "constructor" &&
 | |
|                     node.parent.kind !== "set" && !isTypeClass(node)) {
 | |
|                     if (requireReturn || (functionData.returnPresent && !node.async)) {
 | |
|                         context.report({
 | |
|                             node: jsdocNode,
 | |
|                             messageId: "missingReturn",
 | |
|                             data: {
 | |
|                                 returns: prefer.returns || "returns"
 | |
|                             }
 | |
|                         });
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // check the parameters
 | |
|                 const jsdocParamNames = Object.keys(paramTagsByName);
 | |
| 
 | |
|                 if (node.params) {
 | |
|                     node.params.forEach((param, paramsIndex) => {
 | |
|                         const bindingParam = param.type === "AssignmentPattern"
 | |
|                             ? param.left
 | |
|                             : param;
 | |
| 
 | |
|                         // TODO(nzakas): Figure out logical things to do with destructured, default, rest params
 | |
|                         if (bindingParam.type === "Identifier") {
 | |
|                             const name = bindingParam.name;
 | |
| 
 | |
|                             if (jsdocParamNames[paramsIndex] && (name !== jsdocParamNames[paramsIndex])) {
 | |
|                                 context.report({
 | |
|                                     node: jsdocNode,
 | |
|                                     messageId: "expected",
 | |
|                                     loc: getAbsoluteRange(jsdocNode, paramTagsByName[jsdocParamNames[paramsIndex]]),
 | |
|                                     data: {
 | |
|                                         name,
 | |
|                                         jsdocName: jsdocParamNames[paramsIndex]
 | |
|                                     }
 | |
|                                 });
 | |
|                             } else if (!paramTagsByName[name] && !isOverride) {
 | |
|                                 context.report({
 | |
|                                     node: jsdocNode,
 | |
|                                     messageId: "missingParam",
 | |
|                                     data: {
 | |
|                                         name
 | |
|                                     }
 | |
|                                 });
 | |
|                             }
 | |
|                         }
 | |
|                     });
 | |
|                 }
 | |
| 
 | |
|                 if (options.matchDescription) {
 | |
|                     const regex = new RegExp(options.matchDescription, "u");
 | |
| 
 | |
|                     if (!regex.test(jsdoc.description)) {
 | |
|                         context.report({ node: jsdocNode, messageId: "unsatisfiedDesc" });
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         //--------------------------------------------------------------------------
 | |
|         // Public
 | |
|         //--------------------------------------------------------------------------
 | |
| 
 | |
|         return {
 | |
|             ArrowFunctionExpression: startFunction,
 | |
|             FunctionExpression: startFunction,
 | |
|             FunctionDeclaration: startFunction,
 | |
|             ClassExpression: startFunction,
 | |
|             ClassDeclaration: startFunction,
 | |
|             "ArrowFunctionExpression:exit": checkJSDoc,
 | |
|             "FunctionExpression:exit": checkJSDoc,
 | |
|             "FunctionDeclaration:exit": checkJSDoc,
 | |
|             "ClassExpression:exit": checkJSDoc,
 | |
|             "ClassDeclaration:exit": checkJSDoc,
 | |
|             ReturnStatement: addReturn
 | |
|         };
 | |
| 
 | |
|     }
 | |
| };
 |