Add comprehensive frontend UI and distributed infrastructure

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>
This commit is contained in:
anthonyrawlins
2025-07-10 08:41:59 +10:00
parent fc0eec91ef
commit 85bf1341f3
28348 changed files with 2646896 additions and 69 deletions

View File

@@ -0,0 +1,208 @@
module.exports = ({ root, jscodeshift }) => {
const findImportIdentifierOf = (importSpecifiers, identifier) => {
const specifier = importSpecifiers
.filter((node) => node.value.imported.name === identifier)
.paths()
if (specifier.length > 0) {
return specifier[0].value.local
}
return jscodeshift.identifier(identifier)
}
const findImportSpecifiers = (packageName) =>
root
.find(jscodeshift.ImportDeclaration, {
source: {
value: packageName,
},
})
.find(jscodeshift.ImportSpecifier, {})
const locateImports = (
identifiers,
packageName = '@tanstack/react-query',
) => {
const findNamespaceImportIdentifier = () => {
const specifier = root
.find(jscodeshift.ImportDeclaration, {
source: {
value: packageName,
},
})
.find(jscodeshift.ImportNamespaceSpecifier)
.paths()
return specifier.length > 0 ? specifier[0].value.local : null
}
/**
* First, we search for the namespace import identifier because if we have any, we assume the consumer uses
* namespace imports. In this case, we won't search for named imports at all.
*/
const namespaceImportIdentifier = findNamespaceImportIdentifier()
if (namespaceImportIdentifier) {
const identifierMap = {}
for (const identifier of identifiers) {
identifierMap[identifier] = jscodeshift.identifier(identifier)
}
return {
namespace: namespaceImportIdentifier,
...identifierMap,
}
}
const importSpecifiers = findImportSpecifiers(packageName)
const identifierMap = {}
for (const identifier of identifiers) {
identifierMap[identifier] = findImportIdentifierOf(
importSpecifiers,
identifier,
)
}
return {
namespace: null,
...identifierMap,
}
}
const findAllMethodCalls = () =>
root
// First, we need to find all method calls.
.find(jscodeshift.CallExpression, {
callee: {
type: jscodeshift.MemberExpression.name,
property: {
type: jscodeshift.Identifier.name,
},
},
})
const findQueryClientIdentifiers = (importIdentifiers) =>
root
.find(jscodeshift.VariableDeclarator, {})
.filter((node) => {
if (node.value.init) {
const initializer = node.value.init
return (
isClassInstantiationOf(
initializer,
getSelectorByImports(importIdentifiers, 'QueryClient'),
) ||
isFunctionCallOf(
initializer,
getSelectorByImports(importIdentifiers, 'useQueryClient'),
)
)
}
return false
})
.paths()
.map((node) => node.value.id.name)
const isCallExpression = (node) =>
jscodeshift.match(node, { type: jscodeshift.CallExpression.name })
const isIdentifier = (node) =>
jscodeshift.match(node, { type: jscodeshift.Identifier.name })
const isMemberExpression = (node) =>
jscodeshift.match(node, { type: jscodeshift.MemberExpression.name })
const isNewExpression = (node) =>
jscodeshift.match(node, { type: jscodeshift.NewExpression.name })
const isArrayExpression = (node) =>
jscodeshift.match(node, { type: jscodeshift.ArrayExpression.name })
const isObjectExpression = (node) =>
jscodeshift.match(node, { type: jscodeshift.ObjectExpression.name })
const isObjectProperty = (node) =>
jscodeshift.match(node, { type: jscodeshift.ObjectProperty.name })
const isSpreadElement = (node) =>
jscodeshift.match(node, { type: jscodeshift.SpreadElement.name })
/**
* @param {import('jscodeshift').Node} node
* @returns {boolean}
*/
const isFunctionDefinition = (node) => {
const isArrowFunctionExpression = jscodeshift.match(node, {
type: jscodeshift.ArrowFunctionExpression.name,
})
const isFunctionExpression = jscodeshift.match(node, {
type: jscodeshift.FunctionExpression.name,
})
return isArrowFunctionExpression || isFunctionExpression
}
const warn = (message) => {
if (process.env.NODE_ENV !== 'test') {
console.warn(message)
}
}
const isClassInstantiationOf = (node, selector) => {
if (!isNewExpression(node)) {
return false
}
const parts = selector.split('.')
return parts.length === 1
? isIdentifier(node.callee) && node.callee.name === parts[0]
: isMemberExpression(node.callee) &&
node.callee.object.name === parts[0] &&
node.callee.property.name === parts[1]
}
const isFunctionCallOf = (node, selector) => {
if (!isCallExpression(node)) {
return false
}
const parts = selector.split('.')
return parts.length === 1
? isIdentifier(node.callee) && node.callee.name === parts[0]
: isMemberExpression(node.callee) &&
node.callee.object.name === parts[0] &&
node.callee.property.name === parts[1]
}
const getSelectorByImports = (imports, path) =>
imports.namespace
? `${imports.namespace.name}.${imports[path].name}`
: imports[path].name
return {
findAllMethodCalls,
getSelectorByImports,
isCallExpression,
isClassInstantiationOf,
isFunctionCallOf,
isIdentifier,
isMemberExpression,
isArrayExpression,
isObjectExpression,
isObjectProperty,
isSpreadElement,
isFunctionDefinition,
locateImports,
warn,
queryClient: {
findQueryClientIdentifiers,
},
}
}

View File

@@ -0,0 +1,124 @@
module.exports = ({
jscodeshift,
utils,
root,
packageName = '@tanstack/react-query',
}) => {
const isGetQueryCacheMethodCall = (
initializer,
importIdentifiers,
knownQueryClientIds,
) => {
const isKnownQueryClient = (node) =>
utils.isIdentifier(node) && knownQueryClientIds.includes(node.name)
const isGetQueryCacheIdentifier = (node) =>
utils.isIdentifier(node) && node.name === 'getQueryCache'
const isValidInitializer = (node) =>
utils.isCallExpression(node) && utils.isMemberExpression(node.callee)
if (isValidInitializer(initializer)) {
const instance = initializer.callee.object
return (
isGetQueryCacheIdentifier(initializer.callee.property) &&
(isKnownQueryClient(instance) ||
utils.isFunctionCallOf(
instance,
utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),
))
)
}
return false
}
const findQueryCacheInstantiations = (
importIdentifiers,
knownQueryClientIds,
) =>
root.find(jscodeshift.VariableDeclarator, {}).filter((node) => {
if (node.value.init) {
const initializer = node.value.init
return (
utils.isClassInstantiationOf(
initializer,
utils.getSelectorByImports(importIdentifiers, 'QueryCache'),
) ||
isGetQueryCacheMethodCall(
initializer,
importIdentifiers,
knownQueryClientIds,
)
)
}
return false
})
const filterQueryCacheMethodCalls = (node) =>
utils.isIdentifier(node) && ['find', 'findAll'].includes(node.name)
const findQueryCacheMethodCalls = (importIdentifiers) => {
/**
* Here we collect all query client instantiations. We have to make aware of them because the query cache can be
* accessed by the query client as well.
*/
const queryClientIdentifiers =
utils.queryClient.findQueryClientIdentifiers(importIdentifiers)
/**
* Here we collect all query cache instantiations. The reason is simple: the methods can be called on query cache
* instances, to locate the possible usages we need to be aware of the identifier names.
*/
const queryCacheIdentifiers = findQueryCacheInstantiations(
importIdentifiers,
queryClientIdentifiers,
)
.paths()
.map((node) => node.value.id.name)
return (
utils
// First, we need to find all method calls.
.findAllMethodCalls()
// Then we narrow the collection to all `fetch` and `fetchAll` methods.
.filter((node) =>
filterQueryCacheMethodCalls(node.value.callee.property),
)
.filter((node) => {
const object = node.value.callee.object
// If the method is called on a `QueryCache` instance, we keep it in the collection.
if (utils.isIdentifier(object)) {
return queryCacheIdentifiers.includes(object.name)
}
// If the method is called on a `QueryClient` instance, we keep it in the collection.
if (utils.isCallExpression(object)) {
return isGetQueryCacheMethodCall(
object,
importIdentifiers,
queryClientIdentifiers,
)
}
return false
})
)
}
const execute = (replacer) => {
findQueryCacheMethodCalls(
utils.locateImports(
['QueryCache', 'QueryClient', 'useQueryClient'],
packageName,
),
).replaceWith(replacer)
}
return {
execute,
}
}

View File

@@ -0,0 +1,53 @@
module.exports = ({
jscodeshift,
utils,
root,
packageName = '@tanstack/react-query',
}) => {
const filterQueryClientMethodCalls = (node, methods) =>
utils.isIdentifier(node) && methods.includes(node.name)
const findQueryClientMethodCalls = (importIdentifiers, methods) => {
/**
* Here we collect all query client instantiations. We have to make aware of them because some method calls might
* be invoked on these instances.
*/
const queryClientIdentifiers =
utils.queryClient.findQueryClientIdentifiers(importIdentifiers)
return (
utils
// First, we need to find all method calls.
.findAllMethodCalls()
// Then we narrow the collection to `QueryClient` methods.
.filter((node) =>
filterQueryClientMethodCalls(node.value.callee.property, methods),
)
.filter((node) => {
const object = node.value.callee.object
// If the method is called on a `QueryClient` instance, we keep it in the collection.
if (utils.isIdentifier(object)) {
return queryClientIdentifiers.includes(object.name)
}
// If the method is called on the return value of `useQueryClient` hook, we keep it in the collection.
return utils.isFunctionCallOf(
object,
utils.getSelectorByImports(importIdentifiers, 'useQueryClient'),
)
})
)
}
const execute = (methods, replacer) => {
findQueryClientMethodCalls(
utils.locateImports(['QueryClient', 'useQueryClient'], packageName),
methods,
).replaceWith(replacer)
}
return {
execute,
}
}

View File

@@ -0,0 +1,38 @@
module.exports = ({
jscodeshift,
utils,
root,
packageName = '@tanstack/react-query',
}) => {
const filterUseQueryLikeHookCalls = (node, importIdentifiers, hooks) => {
for (const hook of hooks) {
const selector = utils.getSelectorByImports(importIdentifiers, hook)
if (utils.isFunctionCallOf(node, selector)) {
return true
}
}
return false
}
const findUseQueryLikeHookCalls = (importIdentifiers, hooks) =>
root
// First, we need to find all call expressions.
.find(jscodeshift.CallExpression, {})
// Then we narrow the collection to the `useQuery` like hook calls.
.filter((node) =>
filterUseQueryLikeHookCalls(node.value, importIdentifiers, hooks),
)
const execute = (hooks, replacer) => {
findUseQueryLikeHookCalls(
utils.locateImports(hooks, packageName),
hooks,
).replaceWith(replacer)
}
return {
execute,
}
}