 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>
		
			
				
	
	
		
			298 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import * as React from 'react';
 | |
| import { Action, UNSAFE_invariant, isRouteErrorResponse, createStaticHandler as createStaticHandler$1, UNSAFE_convertRoutesToDataRoutes, IDLE_NAVIGATION, IDLE_FETCHER, IDLE_BLOCKER } from '@remix-run/router';
 | |
| import { UNSAFE_useRoutesImpl, UNSAFE_mapRouteProperties } from 'react-router';
 | |
| import { parsePath, Router, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_FetchersContext, UNSAFE_ViewTransitionContext, createPath } from 'react-router-dom';
 | |
| 
 | |
| /**
 | |
|  * A `<Router>` that may not navigate to any other location. This is useful
 | |
|  * on the server where there is no stateful UI.
 | |
|  */
 | |
| function StaticRouter({
 | |
|   basename,
 | |
|   children,
 | |
|   location: locationProp = "/",
 | |
|   future
 | |
| }) {
 | |
|   if (typeof locationProp === "string") {
 | |
|     locationProp = parsePath(locationProp);
 | |
|   }
 | |
|   let action = Action.Pop;
 | |
|   let location = {
 | |
|     pathname: locationProp.pathname || "/",
 | |
|     search: locationProp.search || "",
 | |
|     hash: locationProp.hash || "",
 | |
|     state: locationProp.state != null ? locationProp.state : null,
 | |
|     key: locationProp.key || "default"
 | |
|   };
 | |
|   let staticNavigator = getStatelessNavigator();
 | |
|   return /*#__PURE__*/React.createElement(Router, {
 | |
|     basename: basename,
 | |
|     children: children,
 | |
|     location: location,
 | |
|     navigationType: action,
 | |
|     navigator: staticNavigator,
 | |
|     future: future,
 | |
|     static: true
 | |
|   });
 | |
| }
 | |
| /**
 | |
|  * A Data Router that may not navigate to any other location. This is useful
 | |
|  * on the server where there is no stateful UI.
 | |
|  */
 | |
| function StaticRouterProvider({
 | |
|   context,
 | |
|   router,
 | |
|   hydrate = true,
 | |
|   nonce
 | |
| }) {
 | |
|   !(router && context) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "You must provide `router` and `context` to <StaticRouterProvider>") : UNSAFE_invariant(false) : void 0;
 | |
|   let dataRouterContext = {
 | |
|     router,
 | |
|     navigator: getStatelessNavigator(),
 | |
|     static: true,
 | |
|     staticContext: context,
 | |
|     basename: context.basename || "/"
 | |
|   };
 | |
|   let fetchersContext = new Map();
 | |
|   let hydrateScript = "";
 | |
|   if (hydrate !== false) {
 | |
|     let data = {
 | |
|       loaderData: context.loaderData,
 | |
|       actionData: context.actionData,
 | |
|       errors: serializeErrors(context.errors)
 | |
|     };
 | |
|     // Use JSON.parse here instead of embedding a raw JS object here to speed
 | |
|     // up parsing on the client.  Dual-stringify is needed to ensure all quotes
 | |
|     // are properly escaped in the resulting string.  See:
 | |
|     //   https://v8.dev/blog/cost-of-javascript-2019#json
 | |
|     let json = htmlEscape(JSON.stringify(JSON.stringify(data)));
 | |
|     hydrateScript = `window.__staticRouterHydrationData = JSON.parse(${json});`;
 | |
|   }
 | |
|   let {
 | |
|     state
 | |
|   } = dataRouterContext.router;
 | |
|   return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(UNSAFE_DataRouterContext.Provider, {
 | |
|     value: dataRouterContext
 | |
|   }, /*#__PURE__*/React.createElement(UNSAFE_DataRouterStateContext.Provider, {
 | |
|     value: state
 | |
|   }, /*#__PURE__*/React.createElement(UNSAFE_FetchersContext.Provider, {
 | |
|     value: fetchersContext
 | |
|   }, /*#__PURE__*/React.createElement(UNSAFE_ViewTransitionContext.Provider, {
 | |
|     value: {
 | |
|       isTransitioning: false
 | |
|     }
 | |
|   }, /*#__PURE__*/React.createElement(Router, {
 | |
|     basename: dataRouterContext.basename,
 | |
|     location: state.location,
 | |
|     navigationType: state.historyAction,
 | |
|     navigator: dataRouterContext.navigator,
 | |
|     static: dataRouterContext.static,
 | |
|     future: {
 | |
|       v7_relativeSplatPath: router.future.v7_relativeSplatPath
 | |
|     }
 | |
|   }, /*#__PURE__*/React.createElement(DataRoutes, {
 | |
|     routes: router.routes,
 | |
|     future: router.future,
 | |
|     state: state
 | |
|   })))))), hydrateScript ? /*#__PURE__*/React.createElement("script", {
 | |
|     suppressHydrationWarning: true,
 | |
|     nonce: nonce,
 | |
|     dangerouslySetInnerHTML: {
 | |
|       __html: hydrateScript
 | |
|     }
 | |
|   }) : null);
 | |
| }
 | |
| function DataRoutes({
 | |
|   routes,
 | |
|   future,
 | |
|   state
 | |
| }) {
 | |
|   return UNSAFE_useRoutesImpl(routes, undefined, state, future);
 | |
| }
 | |
| function serializeErrors(errors) {
 | |
|   if (!errors) return null;
 | |
|   let entries = Object.entries(errors);
 | |
|   let serialized = {};
 | |
|   for (let [key, val] of entries) {
 | |
|     // Hey you!  If you change this, please change the corresponding logic in
 | |
|     // deserializeErrors in react-router-dom/index.tsx :)
 | |
|     if (isRouteErrorResponse(val)) {
 | |
|       serialized[key] = {
 | |
|         ...val,
 | |
|         __type: "RouteErrorResponse"
 | |
|       };
 | |
|     } else if (val instanceof Error) {
 | |
|       // Do not serialize stack traces from SSR for security reasons
 | |
|       serialized[key] = {
 | |
|         message: val.message,
 | |
|         __type: "Error",
 | |
|         // If this is a subclass (i.e., ReferenceError), send up the type so we
 | |
|         // can re-create the same type during hydration.
 | |
|         ...(val.name !== "Error" ? {
 | |
|           __subType: val.name
 | |
|         } : {})
 | |
|       };
 | |
|     } else {
 | |
|       serialized[key] = val;
 | |
|     }
 | |
|   }
 | |
|   return serialized;
 | |
| }
 | |
| function getStatelessNavigator() {
 | |
|   return {
 | |
|     createHref,
 | |
|     encodeLocation,
 | |
|     push(to) {
 | |
|       throw new Error(`You cannot use navigator.push() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${JSON.stringify(to)})\` somewhere in your app.`);
 | |
|     },
 | |
|     replace(to) {
 | |
|       throw new Error(`You cannot use navigator.replace() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${JSON.stringify(to)}, { replace: true })\` somewhere ` + `in your app.`);
 | |
|     },
 | |
|     go(delta) {
 | |
|       throw new Error(`You cannot use navigator.go() on the server because it is a stateless ` + `environment. This error was probably triggered when you did a ` + `\`navigate(${delta})\` somewhere in your app.`);
 | |
|     },
 | |
|     back() {
 | |
|       throw new Error(`You cannot use navigator.back() on the server because it is a stateless ` + `environment.`);
 | |
|     },
 | |
|     forward() {
 | |
|       throw new Error(`You cannot use navigator.forward() on the server because it is a stateless ` + `environment.`);
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function createStaticHandler(routes, opts) {
 | |
|   return createStaticHandler$1(routes, {
 | |
|     ...opts,
 | |
|     mapRouteProperties: UNSAFE_mapRouteProperties
 | |
|   });
 | |
| }
 | |
| function createStaticRouter(routes, context, opts = {}) {
 | |
|   let manifest = {};
 | |
|   let dataRoutes = UNSAFE_convertRoutesToDataRoutes(routes, UNSAFE_mapRouteProperties, undefined, manifest);
 | |
| 
 | |
|   // Because our context matches may be from a framework-agnostic set of
 | |
|   // routes passed to createStaticHandler(), we update them here with our
 | |
|   // newly created/enhanced data routes
 | |
|   let matches = context.matches.map(match => {
 | |
|     let route = manifest[match.route.id] || match.route;
 | |
|     return {
 | |
|       ...match,
 | |
|       route
 | |
|     };
 | |
|   });
 | |
|   let msg = method => `You cannot use router.${method}() on the server because it is a stateless environment`;
 | |
|   return {
 | |
|     get basename() {
 | |
|       return context.basename;
 | |
|     },
 | |
|     get future() {
 | |
|       return {
 | |
|         v7_fetcherPersist: false,
 | |
|         v7_normalizeFormMethod: false,
 | |
|         v7_partialHydration: opts.future?.v7_partialHydration === true,
 | |
|         v7_prependBasename: false,
 | |
|         v7_relativeSplatPath: opts.future?.v7_relativeSplatPath === true,
 | |
|         v7_skipActionErrorRevalidation: false
 | |
|       };
 | |
|     },
 | |
|     get state() {
 | |
|       return {
 | |
|         historyAction: Action.Pop,
 | |
|         location: context.location,
 | |
|         matches,
 | |
|         loaderData: context.loaderData,
 | |
|         actionData: context.actionData,
 | |
|         errors: context.errors,
 | |
|         initialized: true,
 | |
|         navigation: IDLE_NAVIGATION,
 | |
|         restoreScrollPosition: null,
 | |
|         preventScrollReset: false,
 | |
|         revalidation: "idle",
 | |
|         fetchers: new Map(),
 | |
|         blockers: new Map()
 | |
|       };
 | |
|     },
 | |
|     get routes() {
 | |
|       return dataRoutes;
 | |
|     },
 | |
|     get window() {
 | |
|       return undefined;
 | |
|     },
 | |
|     initialize() {
 | |
|       throw msg("initialize");
 | |
|     },
 | |
|     subscribe() {
 | |
|       throw msg("subscribe");
 | |
|     },
 | |
|     enableScrollRestoration() {
 | |
|       throw msg("enableScrollRestoration");
 | |
|     },
 | |
|     navigate() {
 | |
|       throw msg("navigate");
 | |
|     },
 | |
|     fetch() {
 | |
|       throw msg("fetch");
 | |
|     },
 | |
|     revalidate() {
 | |
|       throw msg("revalidate");
 | |
|     },
 | |
|     createHref,
 | |
|     encodeLocation,
 | |
|     getFetcher() {
 | |
|       return IDLE_FETCHER;
 | |
|     },
 | |
|     deleteFetcher() {
 | |
|       throw msg("deleteFetcher");
 | |
|     },
 | |
|     dispose() {
 | |
|       throw msg("dispose");
 | |
|     },
 | |
|     getBlocker() {
 | |
|       return IDLE_BLOCKER;
 | |
|     },
 | |
|     deleteBlocker() {
 | |
|       throw msg("deleteBlocker");
 | |
|     },
 | |
|     patchRoutes() {
 | |
|       throw msg("patchRoutes");
 | |
|     },
 | |
|     _internalFetchControllers: new Map(),
 | |
|     _internalActiveDeferreds: new Map(),
 | |
|     _internalSetRoutes() {
 | |
|       throw msg("_internalSetRoutes");
 | |
|     }
 | |
|   };
 | |
| }
 | |
| function createHref(to) {
 | |
|   return typeof to === "string" ? to : createPath(to);
 | |
| }
 | |
| function encodeLocation(to) {
 | |
|   let href = typeof to === "string" ? to : createPath(to);
 | |
|   // Treating this as a full URL will strip any trailing spaces so we need to
 | |
|   // pre-encode them since they might be part of a matching splat param from
 | |
|   // an ancestor route
 | |
|   href = href.replace(/ $/, "%20");
 | |
|   let encoded = ABSOLUTE_URL_REGEX.test(href) ? new URL(href) : new URL(href, "http://localhost");
 | |
|   return {
 | |
|     pathname: encoded.pathname,
 | |
|     search: encoded.search,
 | |
|     hash: encoded.hash
 | |
|   };
 | |
| }
 | |
| const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
 | |
| 
 | |
| // This utility is based on https://github.com/zertosh/htmlescape
 | |
| // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
 | |
| const ESCAPE_LOOKUP = {
 | |
|   "&": "\\u0026",
 | |
|   ">": "\\u003e",
 | |
|   "<": "\\u003c",
 | |
|   "\u2028": "\\u2028",
 | |
|   "\u2029": "\\u2029"
 | |
| };
 | |
| const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
 | |
| function htmlEscape(str) {
 | |
|   return str.replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
 | |
| }
 | |
| 
 | |
| export { StaticRouter, StaticRouterProvider, createStaticHandler, createStaticRouter };
 |