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,5 @@
import { type FC, type PropsWithChildren } from 'react';
import type { ControlButtonProps } from './types';
declare const ControlButton: FC<PropsWithChildren<ControlButtonProps>>;
export default ControlButton;
//# sourceMappingURL=ControlButton.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ControlButton.d.ts","sourceRoot":"","sources":["../../../packages/controls/src/ControlButton.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAI5D,CAAC;AAIF,eAAe,aAAa,CAAC"}

View File

@@ -0,0 +1,5 @@
import React from 'react';
import type { ControlProps } from './types';
declare const _default: React.NamedExoticComponent<React.PropsWithChildren<ControlProps>>;
export default _default;
//# sourceMappingURL=Controls.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Controls.d.ts","sourceRoot":"","sources":["../../../packages/controls/src/Controls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqE,MAAM,OAAO,CAAC;AAY1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;;AAoH5C,wBAA8B"}

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
declare function FitViewIcon(): JSX.Element;
export default FitViewIcon;
//# sourceMappingURL=FitView.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FitView.d.ts","sourceRoot":"","sources":["../../../../packages/controls/src/Icons/FitView.tsx"],"names":[],"mappings":";AAEA,iBAAS,WAAW,gBAMnB;AAED,eAAe,WAAW,CAAC"}

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
declare function LockIcon(): JSX.Element;
export default LockIcon;
//# sourceMappingURL=Lock.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Lock.d.ts","sourceRoot":"","sources":["../../../../packages/controls/src/Icons/Lock.tsx"],"names":[],"mappings":";AAEA,iBAAS,QAAQ,gBAMhB;AAED,eAAe,QAAQ,CAAC"}

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
declare function MinusIcon(): JSX.Element;
export default MinusIcon;
//# sourceMappingURL=Minus.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Minus.d.ts","sourceRoot":"","sources":["../../../../packages/controls/src/Icons/Minus.tsx"],"names":[],"mappings":";AAEA,iBAAS,SAAS,gBAMjB;AAED,eAAe,SAAS,CAAC"}

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
declare function PlusIcon(): JSX.Element;
export default PlusIcon;
//# sourceMappingURL=Plus.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Plus.d.ts","sourceRoot":"","sources":["../../../../packages/controls/src/Icons/Plus.tsx"],"names":[],"mappings":";AAEA,iBAAS,QAAQ,gBAMhB;AAED,eAAe,QAAQ,CAAC"}

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
declare function UnlockIcon(): JSX.Element;
export default UnlockIcon;
//# sourceMappingURL=Unlock.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Unlock.d.ts","sourceRoot":"","sources":["../../../../packages/controls/src/Icons/Unlock.tsx"],"names":[],"mappings":";AAEA,iBAAS,UAAU,gBAMlB;AAED,eAAe,UAAU,CAAC"}

View File

@@ -0,0 +1,4 @@
export { default as Controls } from './Controls';
export { default as ControlButton } from './ControlButton';
export * from './types';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/controls/src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,cAAc,SAAS,CAAC"}

View File

@@ -0,0 +1,84 @@
import React, { memo, useState, useEffect } from 'react';
import cc from 'classcat';
import { shallow } from 'zustand/shallow';
import { useStoreApi, useStore, useReactFlow, Panel } from '@reactflow/core';
function PlusIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 32" },
React.createElement("path", { d: "M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z" })));
}
function MinusIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 5" },
React.createElement("path", { d: "M0 0h32v4.2H0z" })));
}
function FitViewIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 30" },
React.createElement("path", { d: "M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" })));
}
function LockIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 32" },
React.createElement("path", { d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" })));
}
function UnlockIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 32" },
React.createElement("path", { d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" })));
}
const ControlButton = ({ children, className, ...rest }) => (React.createElement("button", { type: "button", className: cc(['react-flow__controls-button', className]), ...rest }, children));
ControlButton.displayName = 'ControlButton';
const selector = (s) => ({
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
minZoomReached: s.transform[2] <= s.minZoom,
maxZoomReached: s.transform[2] >= s.maxZoom,
});
const Controls = ({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', }) => {
const store = useStoreApi();
const [isVisible, setIsVisible] = useState(false);
const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector, shallow);
const { zoomIn, zoomOut, fitView } = useReactFlow();
useEffect(() => {
setIsVisible(true);
}, []);
if (!isVisible) {
return null;
}
const onZoomInHandler = () => {
zoomIn();
onZoomIn?.();
};
const onZoomOutHandler = () => {
zoomOut();
onZoomOut?.();
};
const onFitViewHandler = () => {
fitView(fitViewOptions);
onFitView?.();
};
const onToggleInteractivity = () => {
store.setState({
nodesDraggable: !isInteractive,
nodesConnectable: !isInteractive,
elementsSelectable: !isInteractive,
});
onInteractiveChange?.(!isInteractive);
};
return (React.createElement(Panel, { className: cc(['react-flow__controls', className]), position: position, style: style, "data-testid": "rf__controls" },
showZoom && (React.createElement(React.Fragment, null,
React.createElement(ControlButton, { onClick: onZoomInHandler, className: "react-flow__controls-zoomin", title: "zoom in", "aria-label": "zoom in", disabled: maxZoomReached },
React.createElement(PlusIcon, null)),
React.createElement(ControlButton, { onClick: onZoomOutHandler, className: "react-flow__controls-zoomout", title: "zoom out", "aria-label": "zoom out", disabled: minZoomReached },
React.createElement(MinusIcon, null)))),
showFitView && (React.createElement(ControlButton, { className: "react-flow__controls-fitview", onClick: onFitViewHandler, title: "fit view", "aria-label": "fit view" },
React.createElement(FitViewIcon, null))),
showInteractive && (React.createElement(ControlButton, { className: "react-flow__controls-interactive", onClick: onToggleInteractivity, title: "toggle interactivity", "aria-label": "toggle interactivity" }, isInteractive ? React.createElement(UnlockIcon, null) : React.createElement(LockIcon, null))),
children));
};
Controls.displayName = 'Controls';
var Controls$1 = memo(Controls);
export { ControlButton, Controls$1 as Controls };

View File

@@ -0,0 +1,84 @@
import React, { memo, useState, useEffect } from 'react';
import cc from 'classcat';
import { shallow } from 'zustand/shallow';
import { useStoreApi, useStore, useReactFlow, Panel } from '@reactflow/core';
function PlusIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 32" },
React.createElement("path", { d: "M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z" })));
}
function MinusIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 5" },
React.createElement("path", { d: "M0 0h32v4.2H0z" })));
}
function FitViewIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 30" },
React.createElement("path", { d: "M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" })));
}
function LockIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 32" },
React.createElement("path", { d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" })));
}
function UnlockIcon() {
return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 32" },
React.createElement("path", { d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" })));
}
const ControlButton = ({ children, className, ...rest }) => (React.createElement("button", { type: "button", className: cc(['react-flow__controls-button', className]), ...rest }, children));
ControlButton.displayName = 'ControlButton';
const selector = (s) => ({
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
minZoomReached: s.transform[2] <= s.minZoom,
maxZoomReached: s.transform[2] >= s.maxZoom,
});
const Controls = ({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', }) => {
const store = useStoreApi();
const [isVisible, setIsVisible] = useState(false);
const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector, shallow);
const { zoomIn, zoomOut, fitView } = useReactFlow();
useEffect(() => {
setIsVisible(true);
}, []);
if (!isVisible) {
return null;
}
const onZoomInHandler = () => {
zoomIn();
onZoomIn?.();
};
const onZoomOutHandler = () => {
zoomOut();
onZoomOut?.();
};
const onFitViewHandler = () => {
fitView(fitViewOptions);
onFitView?.();
};
const onToggleInteractivity = () => {
store.setState({
nodesDraggable: !isInteractive,
nodesConnectable: !isInteractive,
elementsSelectable: !isInteractive,
});
onInteractiveChange?.(!isInteractive);
};
return (React.createElement(Panel, { className: cc(['react-flow__controls', className]), position: position, style: style, "data-testid": "rf__controls" },
showZoom && (React.createElement(React.Fragment, null,
React.createElement(ControlButton, { onClick: onZoomInHandler, className: "react-flow__controls-zoomin", title: "zoom in", "aria-label": "zoom in", disabled: maxZoomReached },
React.createElement(PlusIcon, null)),
React.createElement(ControlButton, { onClick: onZoomOutHandler, className: "react-flow__controls-zoomout", title: "zoom out", "aria-label": "zoom out", disabled: minZoomReached },
React.createElement(MinusIcon, null)))),
showFitView && (React.createElement(ControlButton, { className: "react-flow__controls-fitview", onClick: onFitViewHandler, title: "fit view", "aria-label": "fit view" },
React.createElement(FitViewIcon, null))),
showInteractive && (React.createElement(ControlButton, { className: "react-flow__controls-interactive", onClick: onToggleInteractivity, title: "toggle interactivity", "aria-label": "toggle interactivity" }, isInteractive ? React.createElement(UnlockIcon, null) : React.createElement(LockIcon, null))),
children));
};
Controls.displayName = 'Controls';
var Controls$1 = memo(Controls);
export { ControlButton, Controls$1 as Controls };

View File

@@ -0,0 +1,15 @@
import type { ButtonHTMLAttributes, HTMLAttributes } from 'react';
import type { FitViewOptions, PanelPosition } from '@reactflow/core';
export type ControlProps = HTMLAttributes<HTMLDivElement> & {
showZoom?: boolean;
showFitView?: boolean;
showInteractive?: boolean;
fitViewOptions?: FitViewOptions;
onZoomIn?: () => void;
onZoomOut?: () => void;
onFitView?: () => void;
onInteractiveChange?: (interactiveStatus: boolean) => void;
position?: PanelPosition;
};
export type ControlButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../packages/controls/src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,mBAAmB,CAAC,EAAE,CAAC,iBAAiB,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC"}