mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
refactor(builder): Update ReactFlow to version 12 & split up Flow.tsx (#7808)
Update ReactFlow to version 12 and split `Flow.tsx` into `useAgentGraph` hook that takes care of agent state and API calls to the server. - Update ReactFlow to v12 ([migration guide](https://reactflow.dev/learn/troubleshooting/migrate-to-v12)) - Move `setIsAnyModalOpen` to `FlowContext` - Make `setHardcodedValues` and `setErrors` functions of `CustomNode` and utilize new `updateNodeData` ReactFlow API - Fix type errors - `useAgentGraph` hook - Take care of all API calls, websocket, agent state and logic - Make saving and execution async and thus more consistent and reliable - Save&run requests are state - Wait for node ids to sync with backend reactively - Queue execution updates - Memoize functions using `useCallback`
This commit is contained in:
committed by
GitHub
parent
1df7d527dd
commit
299530cf95
@@ -28,6 +28,7 @@
|
||||
"@radix-ui/react-tooltip": "^1.1.2",
|
||||
"@supabase/ssr": "^0.4.0",
|
||||
"@supabase/supabase-js": "^2.45.0",
|
||||
"@xyflow/react": "^12.1.0",
|
||||
"ajv": "^8.17.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -45,7 +46,6 @@
|
||||
"react-icons": "^5.2.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-modal": "^3.16.1",
|
||||
"reactflow": "^11.11.4",
|
||||
"recharts": "^2.12.7",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
ArrowLeft,
|
||||
@@ -13,27 +13,24 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { AgentDetailResponse } from "@/lib/marketplace-api";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Node, Edge, NodeTypes, EdgeTypes } from "reactflow";
|
||||
import { Node, Edge } from "@xyflow/react";
|
||||
import MarketplaceAPI from "@/lib/marketplace-api";
|
||||
import AutoGPTServerAPI, { GraphCreatable } from "@/lib/autogpt-server-api";
|
||||
|
||||
const ReactFlow = dynamic(
|
||||
() => import("reactflow").then((mod) => mod.default),
|
||||
() => import("@xyflow/react").then((mod) => mod.ReactFlow),
|
||||
{ ssr: false },
|
||||
);
|
||||
const Controls = dynamic(
|
||||
() => import("reactflow").then((mod) => mod.Controls),
|
||||
() => import("@xyflow/react").then((mod) => mod.Controls),
|
||||
{ ssr: false },
|
||||
);
|
||||
const Background = dynamic(
|
||||
() => import("reactflow").then((mod) => mod.Background),
|
||||
() => import("@xyflow/react").then((mod) => mod.Background),
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
import "reactflow/dist/style.css";
|
||||
import CustomNode from "./CustomNode";
|
||||
import { CustomEdge } from "./CustomEdge";
|
||||
import ConnectionLine from "./ConnectionLine";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import { beautifyString } from "@/lib/utils";
|
||||
|
||||
function convertGraphToReactFlow(graph: any): { nodes: Node[]; edges: Edge[] } {
|
||||
@@ -111,9 +108,6 @@ function AgentDetailContent({ agent }: { agent: AgentDetailResponse }) {
|
||||
const [isGraphExpanded, setIsGraphExpanded] = useState(false);
|
||||
const { nodes, edges } = convertGraphToReactFlow(agent.graph);
|
||||
|
||||
const nodeTypes: NodeTypes = useMemo(() => ({ custom: CustomNode }), []);
|
||||
const edgeTypes: EdgeTypes = useMemo(() => ({ custom: CustomEdge }), []);
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl px-4 py-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
ConnectionLineComponentProps,
|
||||
getBezierPath,
|
||||
Position,
|
||||
} from "reactflow";
|
||||
} from "@xyflow/react";
|
||||
|
||||
const ConnectionLine: React.FC<ConnectionLineComponentProps> = ({
|
||||
fromPosition,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import React, { FC, memo, useContext, useEffect, useState } from "react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import {
|
||||
BaseEdge,
|
||||
EdgeLabelRenderer,
|
||||
EdgeProps,
|
||||
useReactFlow,
|
||||
XYPosition,
|
||||
} from "reactflow";
|
||||
Edge,
|
||||
Node,
|
||||
} from "@xyflow/react";
|
||||
import "./customedge.css";
|
||||
import { X } from "lucide-react";
|
||||
import { useBezierPath } from "@/hooks/useBezierPath";
|
||||
@@ -26,7 +28,9 @@ type Bead = {
|
||||
startTime: number;
|
||||
};
|
||||
|
||||
const CustomEdgeFC: FC<EdgeProps<CustomEdgeData>> = ({
|
||||
export type CustomEdge = Edge<CustomEdgeData, "custom">;
|
||||
|
||||
export function CustomEdge({
|
||||
id,
|
||||
data,
|
||||
selected,
|
||||
@@ -35,7 +39,7 @@ const CustomEdgeFC: FC<EdgeProps<CustomEdgeData>> = ({
|
||||
targetX,
|
||||
targetY,
|
||||
markerEnd,
|
||||
}) => {
|
||||
}: EdgeProps<CustomEdge>) {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [beads, setBeads] = useState<{
|
||||
beads: Bead[];
|
||||
@@ -48,7 +52,7 @@ const CustomEdgeFC: FC<EdgeProps<CustomEdgeData>> = ({
|
||||
targetX + 3,
|
||||
targetY,
|
||||
);
|
||||
const { deleteElements } = useReactFlow<any, CustomEdgeData>();
|
||||
const { deleteElements } = useReactFlow<Node, CustomEdge>();
|
||||
const { visualizeBeads } = useContext(FlowContext) ?? {
|
||||
visualizeBeads: "no",
|
||||
};
|
||||
@@ -225,6 +229,4 @@ const CustomEdgeFC: FC<EdgeProps<CustomEdgeData>> = ({
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const CustomEdge = memo(CustomEdgeFC);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import React, {
|
||||
useState,
|
||||
useEffect,
|
||||
FC,
|
||||
memo,
|
||||
useCallback,
|
||||
useRef,
|
||||
useContext,
|
||||
} from "react";
|
||||
import { NodeProps, useReactFlow } from "reactflow";
|
||||
import "reactflow/dist/style.css";
|
||||
import { NodeProps, useReactFlow, Node, Edge } from "@xyflow/react";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import "./customnode.css";
|
||||
import InputModalComponent from "./InputModalComponent";
|
||||
import OutputModalComponent from "./OutputModalComponent";
|
||||
import {
|
||||
BlockIORootSchema,
|
||||
Category,
|
||||
NodeExecutionResult,
|
||||
} from "@/lib/autogpt-server-api/types";
|
||||
import { beautifyString, setNestedProperty } from "@/lib/utils";
|
||||
@@ -24,6 +24,7 @@ import NodeHandle from "./NodeHandle";
|
||||
import { NodeGenericInputField } from "./node-input-components";
|
||||
import SchemaTooltip from "./SchemaTooltip";
|
||||
import { getPrimaryCategoryColor } from "@/lib/utils";
|
||||
import { FlowContext } from "./Flow";
|
||||
|
||||
type ParsedKey = { key: string; index?: number };
|
||||
|
||||
@@ -39,24 +40,23 @@ export type CustomNodeData = {
|
||||
blockType: string;
|
||||
title: string;
|
||||
description: string;
|
||||
categories: string[];
|
||||
categories: Category[];
|
||||
inputSchema: BlockIORootSchema;
|
||||
outputSchema: BlockIORootSchema;
|
||||
hardcodedValues: { [key: string]: any };
|
||||
setHardcodedValues: (values: { [key: string]: any }) => void;
|
||||
connections: ConnectionData;
|
||||
isOutputOpen: boolean;
|
||||
status?: NodeExecutionResult["status"];
|
||||
output_data?: NodeExecutionResult["output_data"];
|
||||
block_id: string;
|
||||
backend_id?: string;
|
||||
errors?: { [key: string]: string | null };
|
||||
setErrors: (errors: { [key: string]: string | null }) => void;
|
||||
setIsAnyModalOpen?: (isOpen: boolean) => void;
|
||||
errors?: { [key: string]: string };
|
||||
isOutputStatic?: boolean;
|
||||
};
|
||||
|
||||
const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
export type CustomNode = Node<CustomNodeData, "custom">;
|
||||
|
||||
export function CustomNode({ data, id }: NodeProps<CustomNode>) {
|
||||
const [isOutputOpen, setIsOutputOpen] = useState(data.isOutputOpen || false);
|
||||
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
@@ -64,11 +64,15 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
const [modalValue, setModalValue] = useState<string>("");
|
||||
const [isOutputModalOpen, setIsOutputModalOpen] = useState(false);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const { deleteElements } = useReactFlow();
|
||||
|
||||
const outputDataRef = useRef<HTMLDivElement>(null);
|
||||
const { updateNodeData, deleteElements } = useReactFlow<CustomNode, Edge>();
|
||||
const isInitialSetup = useRef(true);
|
||||
const flowContext = useContext(FlowContext);
|
||||
|
||||
if (!flowContext) {
|
||||
throw new Error("FlowContext consumer must be inside FlowEditor component");
|
||||
}
|
||||
|
||||
const { setIsAnyModalOpen } = flowContext;
|
||||
|
||||
useEffect(() => {
|
||||
if (data.output_data || data.status) {
|
||||
@@ -81,13 +85,21 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
}, [data.isOutputOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
data.setIsAnyModalOpen?.(isModalOpen || isOutputModalOpen);
|
||||
setIsAnyModalOpen?.(isModalOpen || isOutputModalOpen);
|
||||
}, [isModalOpen, isOutputModalOpen, data]);
|
||||
|
||||
useEffect(() => {
|
||||
isInitialSetup.current = false;
|
||||
}, []);
|
||||
|
||||
const setHardcodedValues = (values: any) => {
|
||||
updateNodeData(id, { hardcodedValues: values });
|
||||
};
|
||||
|
||||
const setErrors = (errors: { [key: string]: string }) => {
|
||||
updateNodeData(id, { errors });
|
||||
};
|
||||
|
||||
const toggleOutput = (checked: boolean) => {
|
||||
setIsOutputOpen(checked);
|
||||
};
|
||||
@@ -148,19 +160,20 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
history.push({
|
||||
type: "UPDATE_INPUT",
|
||||
payload: { nodeId: id, oldValues: data.hardcodedValues, newValues },
|
||||
undo: () => data.setHardcodedValues(data.hardcodedValues),
|
||||
redo: () => data.setHardcodedValues(newValues),
|
||||
undo: () => setHardcodedValues(data.hardcodedValues),
|
||||
redo: () => setHardcodedValues(newValues),
|
||||
});
|
||||
}
|
||||
|
||||
data.setHardcodedValues(newValues);
|
||||
setHardcodedValues(newValues);
|
||||
const errors = data.errors || {};
|
||||
// Remove error with the same key
|
||||
setNestedProperty(errors, path, null);
|
||||
data.setErrors({ ...errors });
|
||||
setErrors({ ...errors });
|
||||
};
|
||||
|
||||
// Helper function to parse keys with array indices
|
||||
//TODO move to utils
|
||||
const parseKeys = (key: string): ParsedKey[] => {
|
||||
const splits = key.split(/_@_|_#_|_\$_|\./);
|
||||
const keys: ParsedKey[] = [];
|
||||
@@ -252,14 +265,6 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const isTextTruncated = (element: HTMLElement | null): boolean => {
|
||||
if (!element) return false;
|
||||
return (
|
||||
element.scrollHeight > element.clientHeight ||
|
||||
element.scrollWidth > element.clientWidth
|
||||
);
|
||||
};
|
||||
|
||||
const handleHovered = () => {
|
||||
setIsHovered(true);
|
||||
};
|
||||
@@ -412,6 +417,4 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(CustomNode);
|
||||
}
|
||||
|
||||
@@ -3,64 +3,47 @@ import React, {
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
MouseEvent,
|
||||
createContext,
|
||||
} from "react";
|
||||
import { shallow } from "zustand/vanilla/shallow";
|
||||
import ReactFlow, {
|
||||
import {
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
Controls,
|
||||
Background,
|
||||
Node,
|
||||
Edge,
|
||||
OnConnect,
|
||||
NodeTypes,
|
||||
Connection,
|
||||
EdgeTypes,
|
||||
MarkerType,
|
||||
NodeChange,
|
||||
EdgeChange,
|
||||
useStore,
|
||||
useReactFlow,
|
||||
applyEdgeChanges,
|
||||
applyNodeChanges,
|
||||
useViewport,
|
||||
} from "reactflow";
|
||||
import "reactflow/dist/style.css";
|
||||
import CustomNode, { CustomNodeData } from "./CustomNode";
|
||||
} from "@xyflow/react";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import { CustomNode } from "./CustomNode";
|
||||
import "./flow.css";
|
||||
import AutoGPTServerAPI, {
|
||||
Block,
|
||||
BlockIOSubSchema,
|
||||
Graph,
|
||||
Link,
|
||||
NodeExecutionResult,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
import {
|
||||
deepEquals,
|
||||
getTypeColor,
|
||||
removeEmptyStringsAndNulls,
|
||||
setNestedProperty,
|
||||
} from "@/lib/utils";
|
||||
import { Link } from "@/lib/autogpt-server-api";
|
||||
import { getTypeColor } from "@/lib/utils";
|
||||
import { history } from "./history";
|
||||
import { CustomEdge, CustomEdgeData } from "./CustomEdge";
|
||||
import { CustomEdge } from "./CustomEdge";
|
||||
import ConnectionLine from "./ConnectionLine";
|
||||
import Ajv from "ajv";
|
||||
import { Control, ControlPanel } from "@/components/edit/control/ControlPanel";
|
||||
import { SaveControl } from "@/components/edit/control/SaveControl";
|
||||
import { BlocksControl } from "@/components/edit/control/BlocksControl";
|
||||
import { IconPlay, IconRedo2, IconUndo2 } from "@/components/ui/icons";
|
||||
import useAgentGraph from "@/hooks/useAgentGraph";
|
||||
|
||||
// This is for the history, this is the minimum distance a block must move before it is logged
|
||||
// It helps to prevent spamming the history with small movements especially when pressing on a input in a block
|
||||
const MINIMUM_MOVE_BEFORE_LOG = 50;
|
||||
|
||||
const ajv = new Ajv({ strict: false, allErrors: true });
|
||||
|
||||
type FlowContextType = {
|
||||
visualizeBeads: "no" | "static" | "animate";
|
||||
setIsAnyModalOpen: (isOpen: boolean) => void;
|
||||
};
|
||||
|
||||
export const FlowContext = createContext<FlowContextType | null>(null);
|
||||
@@ -70,79 +53,36 @@ const FlowEditor: React.FC<{
|
||||
template?: boolean;
|
||||
className?: string;
|
||||
}> = ({ flowID, template, className }) => {
|
||||
const { _setNodes, _setEdges } = useStore(
|
||||
useCallback(
|
||||
({ setNodes, setEdges }) => ({
|
||||
_setNodes: setNodes,
|
||||
_setEdges: setEdges,
|
||||
}),
|
||||
[],
|
||||
),
|
||||
shallow,
|
||||
);
|
||||
const {
|
||||
addNodes,
|
||||
addEdges,
|
||||
getNode,
|
||||
getNodes,
|
||||
getEdges,
|
||||
setNodes,
|
||||
setEdges,
|
||||
deleteElements,
|
||||
} = useReactFlow<CustomNodeData, CustomEdgeData>();
|
||||
const { addNodes, addEdges, getNode, deleteElements, updateNode } =
|
||||
useReactFlow<CustomNode, CustomEdge>();
|
||||
const [nodeId, setNodeId] = useState<number>(1);
|
||||
const [availableNodes, setAvailableNodes] = useState<Block[]>([]);
|
||||
const [savedAgent, setSavedAgent] = useState<Graph | null>(null);
|
||||
const [agentDescription, setAgentDescription] = useState<string>("");
|
||||
const [agentName, setAgentName] = useState<string>("");
|
||||
const [copiedNodes, setCopiedNodes] = useState<Node<CustomNodeData>[]>([]);
|
||||
const [copiedEdges, setCopiedEdges] = useState<Edge<CustomEdgeData>[]>([]);
|
||||
const [isAnyModalOpen, setIsAnyModalOpen] = useState(false); // Track if any modal is open
|
||||
const [copiedNodes, setCopiedNodes] = useState<CustomNode[]>([]);
|
||||
const [copiedEdges, setCopiedEdges] = useState<CustomEdge[]>([]);
|
||||
const [isAnyModalOpen, setIsAnyModalOpen] = useState(false);
|
||||
const [visualizeBeads, setVisualizeBeads] = useState<
|
||||
"no" | "static" | "animate"
|
||||
>("animate");
|
||||
const {
|
||||
agentName,
|
||||
setAgentName,
|
||||
agentDescription,
|
||||
setAgentDescription,
|
||||
savedAgent,
|
||||
availableNodes,
|
||||
getOutputType,
|
||||
requestSave,
|
||||
requestSaveRun,
|
||||
nodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = useAgentGraph(flowID, template, visualizeBeads !== "no");
|
||||
|
||||
const apiUrl = process.env.NEXT_PUBLIC_AGPT_SERVER_URL!;
|
||||
const api = useMemo(() => new AutoGPTServerAPI(apiUrl), [apiUrl]);
|
||||
const initialPositionRef = useRef<{
|
||||
[key: string]: { x: number; y: number };
|
||||
}>({});
|
||||
const isDragging = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
api
|
||||
.connectWebSocket()
|
||||
.then(() => {
|
||||
console.log("WebSocket connected");
|
||||
api.onWebSocketMessage("execution_event", (data) => {
|
||||
updateNodesWithExecutionData([data]);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to connect WebSocket:", error);
|
||||
});
|
||||
|
||||
return () => {
|
||||
api.disconnectWebSocket();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
useEffect(() => {
|
||||
api
|
||||
.getBlocks()
|
||||
.then((blocks) => setAvailableNodes(blocks))
|
||||
.catch();
|
||||
}, []);
|
||||
|
||||
// Load existing graph
|
||||
useEffect(() => {
|
||||
if (!flowID || availableNodes.length == 0) return;
|
||||
|
||||
(template ? api.getTemplate(flowID) : api.getGraph(flowID)).then((graph) =>
|
||||
loadGraph(graph),
|
||||
);
|
||||
}, [flowID, template, availableNodes]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
|
||||
@@ -170,9 +110,6 @@ const FlowEditor: React.FC<{
|
||||
};
|
||||
}, []);
|
||||
|
||||
const nodeTypes: NodeTypes = useMemo(() => ({ custom: CustomNode }), []);
|
||||
const edgeTypes: EdgeTypes = useMemo(() => ({ custom: CustomEdge }), []);
|
||||
|
||||
const onNodeDragStart = (_: MouseEvent, node: Node) => {
|
||||
initialPositionRef.current[node.id] = { ...node.position };
|
||||
isDragging.current = true;
|
||||
@@ -198,37 +135,13 @@ const FlowEditor: React.FC<{
|
||||
history.push({
|
||||
type: "UPDATE_NODE_POSITION",
|
||||
payload: { nodeId: node.id, oldPosition, newPosition },
|
||||
undo: () =>
|
||||
// TODO: replace with updateNodes() after upgrade to ReactFlow v12
|
||||
setNodes((nds) =>
|
||||
nds.map((n) =>
|
||||
n.id === node.id ? { ...n, position: oldPosition } : n,
|
||||
),
|
||||
),
|
||||
redo: () =>
|
||||
// TODO: replace with updateNodes() after upgrade to ReactFlow v12
|
||||
setNodes((nds) =>
|
||||
nds.map((n) =>
|
||||
n.id === node.id ? { ...n, position: newPosition } : n,
|
||||
),
|
||||
),
|
||||
undo: () => updateNode(node.id, { position: oldPosition }),
|
||||
redo: () => updateNode(node.id, { position: newPosition }),
|
||||
});
|
||||
}
|
||||
delete initialPositionRef.current[node.id];
|
||||
};
|
||||
|
||||
const getOutputType = (id: string, handleId: string) => {
|
||||
const node = getNode(id);
|
||||
if (!node) return "unknown";
|
||||
|
||||
const outputSchema = node.data.outputSchema;
|
||||
if (!outputSchema) return "unknown";
|
||||
|
||||
const outputHandle = outputSchema.properties[handleId];
|
||||
if (!("type" in outputHandle)) return "unknown";
|
||||
return outputHandle.type;
|
||||
};
|
||||
|
||||
// Function to clear status, output, and close the output info dropdown of all nodes
|
||||
// and reset data beads on edges
|
||||
const clearNodesStatusAndOutput = useCallback(() => {
|
||||
@@ -239,7 +152,7 @@ const FlowEditor: React.FC<{
|
||||
...node.data,
|
||||
status: undefined,
|
||||
output_data: undefined,
|
||||
isOutputOpen: false, // Close the output info dropdown
|
||||
isOutputOpen: false,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -248,9 +161,9 @@ const FlowEditor: React.FC<{
|
||||
}, [setNodes]);
|
||||
|
||||
const onNodesChange = useCallback(
|
||||
(nodeChanges: NodeChange[]) => {
|
||||
(nodeChanges: NodeChange<CustomNode>[]) => {
|
||||
// Persist the changes
|
||||
_setNodes(applyNodeChanges(nodeChanges, getNodes()));
|
||||
setNodes((prev) => applyNodeChanges(nodeChanges, prev));
|
||||
|
||||
// Remove all edges that were connected to deleted nodes
|
||||
nodeChanges
|
||||
@@ -258,7 +171,7 @@ const FlowEditor: React.FC<{
|
||||
.forEach((deletedNode) => {
|
||||
const nodeID = deletedNode.id;
|
||||
|
||||
const connectedEdges = getEdges().filter((edge) =>
|
||||
const connectedEdges = edges.filter((edge) =>
|
||||
[edge.source, edge.target].includes(nodeID),
|
||||
);
|
||||
deleteElements({
|
||||
@@ -266,16 +179,24 @@ const FlowEditor: React.FC<{
|
||||
});
|
||||
});
|
||||
},
|
||||
[getNodes, getEdges, _setNodes, deleteElements],
|
||||
[deleteElements, setNodes],
|
||||
);
|
||||
|
||||
const formatEdgeID = useCallback((conn: Link | Connection): string => {
|
||||
if ("sink_id" in conn) {
|
||||
return `${conn.source_id}_${conn.source_name}_${conn.sink_id}_${conn.sink_name}`;
|
||||
} else {
|
||||
return `${conn.source}_${conn.sourceHandle}_${conn.target}_${conn.targetHandle}`;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onConnect: OnConnect = useCallback(
|
||||
(connection: Connection) => {
|
||||
const edgeColor = getTypeColor(
|
||||
getOutputType(connection.source!, connection.sourceHandle!),
|
||||
);
|
||||
const sourceNode = getNode(connection.source!);
|
||||
const newEdge: Edge<CustomEdgeData> = {
|
||||
const newEdge: CustomEdge = {
|
||||
id: formatEdgeID(connection),
|
||||
type: "custom",
|
||||
markerEnd: {
|
||||
@@ -310,19 +231,23 @@ const FlowEditor: React.FC<{
|
||||
);
|
||||
|
||||
const onEdgesChange = useCallback(
|
||||
(edgeChanges: EdgeChange[]) => {
|
||||
(edgeChanges: EdgeChange<CustomEdge>[]) => {
|
||||
// Persist the changes
|
||||
_setEdges(applyEdgeChanges(edgeChanges, getEdges()));
|
||||
setEdges((prev) => applyEdgeChanges(edgeChanges, prev));
|
||||
|
||||
// Propagate edge changes to node data
|
||||
const addedEdges = edgeChanges.filter((change) => change.type == "add"),
|
||||
resetEdges = edgeChanges.filter((change) => change.type == "reset"),
|
||||
removedEdges = edgeChanges.filter((change) => change.type == "remove"),
|
||||
selectedEdges = edgeChanges.filter((change) => change.type == "select");
|
||||
const addedEdges = edgeChanges.filter((change) => change.type === "add"),
|
||||
replaceEdges = edgeChanges.filter(
|
||||
(change) => change.type === "replace",
|
||||
),
|
||||
removedEdges = edgeChanges.filter((change) => change.type === "remove"),
|
||||
selectedEdges = edgeChanges.filter(
|
||||
(change) => change.type === "select",
|
||||
);
|
||||
|
||||
if (addedEdges.length > 0 || removedEdges.length > 0) {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) => ({
|
||||
setNodes((nds) => {
|
||||
const newNodes = nds.map((node) => ({
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
@@ -331,7 +256,7 @@ const FlowEditor: React.FC<{
|
||||
...node.data.connections.filter(
|
||||
(conn) =>
|
||||
!removedEdges.some(
|
||||
(removedEdge) => removedEdge.id == conn.edge_id,
|
||||
(removedEdge) => removedEdge.id === conn.edge_id,
|
||||
),
|
||||
),
|
||||
// Add node connections for added edges
|
||||
@@ -344,20 +269,22 @@ const FlowEditor: React.FC<{
|
||||
})),
|
||||
],
|
||||
},
|
||||
})),
|
||||
);
|
||||
}));
|
||||
|
||||
return newNodes;
|
||||
});
|
||||
|
||||
if (removedEdges.length > 0) {
|
||||
clearNodesStatusAndOutput(); // Clear status and output on edge deletion
|
||||
}
|
||||
}
|
||||
|
||||
if (resetEdges.length > 0) {
|
||||
if (replaceEdges.length > 0) {
|
||||
// Reset node connections for all edges
|
||||
console.warn(
|
||||
"useReactFlow().setEdges was used to overwrite all edges. " +
|
||||
"useReactFlow().setRootEdges was used to overwrite all edges. " +
|
||||
"Use addEdges, deleteElements, or reconnectEdge for incremental changes.",
|
||||
resetEdges,
|
||||
replaceEdges,
|
||||
);
|
||||
setNodes((nds) =>
|
||||
nds.map((node) => ({
|
||||
@@ -365,12 +292,12 @@ const FlowEditor: React.FC<{
|
||||
data: {
|
||||
...node.data,
|
||||
connections: [
|
||||
...resetEdges.map((resetEdge) => ({
|
||||
edge_id: resetEdge.item.id,
|
||||
source: resetEdge.item.source,
|
||||
target: resetEdge.item.target,
|
||||
sourceHandle: resetEdge.item.sourceHandle!,
|
||||
targetHandle: resetEdge.item.targetHandle!,
|
||||
...replaceEdges.map((replaceEdge) => ({
|
||||
edge_id: replaceEdge.item.id,
|
||||
source: replaceEdge.item.source,
|
||||
target: replaceEdge.item.target,
|
||||
sourceHandle: replaceEdge.item.sourceHandle!,
|
||||
targetHandle: replaceEdge.item.targetHandle!,
|
||||
})),
|
||||
],
|
||||
},
|
||||
@@ -379,7 +306,7 @@ const FlowEditor: React.FC<{
|
||||
clearNodesStatusAndOutput();
|
||||
}
|
||||
},
|
||||
[getEdges, _setEdges, setNodes, clearNodesStatusAndOutput],
|
||||
[setNodes, clearNodesStatusAndOutput],
|
||||
);
|
||||
|
||||
const { x, y, zoom } = useViewport();
|
||||
@@ -398,7 +325,7 @@ const FlowEditor: React.FC<{
|
||||
y: (window.innerHeight / 2 - y) / zoom,
|
||||
};
|
||||
|
||||
const newNode: Node<CustomNodeData> = {
|
||||
const newNode: CustomNode = {
|
||||
id: nodeId.toString(),
|
||||
type: "custom",
|
||||
position: viewportCenter, // Set the position to the calculated viewport center
|
||||
@@ -410,30 +337,9 @@ const FlowEditor: React.FC<{
|
||||
inputSchema: nodeSchema.inputSchema,
|
||||
outputSchema: nodeSchema.outputSchema,
|
||||
hardcodedValues: {},
|
||||
setHardcodedValues: (values) => {
|
||||
// TODO: replace with updateNodes() after upgrade to ReactFlow v12
|
||||
setNodes((nds) =>
|
||||
nds.map((node) =>
|
||||
node.id === newNode.id
|
||||
? { ...node, data: { ...node.data, hardcodedValues: values } }
|
||||
: node,
|
||||
),
|
||||
);
|
||||
},
|
||||
connections: [],
|
||||
isOutputOpen: false,
|
||||
block_id: blockId,
|
||||
setIsAnyModalOpen,
|
||||
setErrors: (errors: { [key: string]: string | null }) => {
|
||||
// TODO: replace with updateNodes() after upgrade to ReactFlow v12
|
||||
setNodes((nds) =>
|
||||
nds.map((node) =>
|
||||
node.id === newNode.id
|
||||
? { ...node, data: { ...node.data, errors } }
|
||||
: node,
|
||||
),
|
||||
);
|
||||
},
|
||||
isOutputStatic: nodeSchema.staticOutput,
|
||||
},
|
||||
};
|
||||
@@ -470,453 +376,6 @@ const FlowEditor: React.FC<{
|
||||
history.redo();
|
||||
};
|
||||
|
||||
function loadGraph(graph: Graph) {
|
||||
setSavedAgent(graph);
|
||||
setAgentName(graph.name);
|
||||
setAgentDescription(graph.description);
|
||||
|
||||
setNodes(() => {
|
||||
const newNodes = graph.nodes.map((node) => {
|
||||
const block = availableNodes.find(
|
||||
(block) => block.id === node.block_id,
|
||||
)!;
|
||||
const newNode: Node<CustomNodeData> = {
|
||||
id: node.id,
|
||||
type: "custom",
|
||||
position: {
|
||||
x: node.metadata.position.x,
|
||||
y: node.metadata.position.y,
|
||||
},
|
||||
data: {
|
||||
block_id: block.id,
|
||||
blockType: block.name,
|
||||
categories: block.categories,
|
||||
description: block.description,
|
||||
title: `${block.name} ${node.id}`,
|
||||
inputSchema: block.inputSchema,
|
||||
outputSchema: block.outputSchema,
|
||||
hardcodedValues: node.input_default,
|
||||
setHardcodedValues: (values: { [key: string]: any }) => {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) =>
|
||||
node.id === newNode.id
|
||||
? {
|
||||
...node,
|
||||
data: { ...node.data, hardcodedValues: values },
|
||||
}
|
||||
: node,
|
||||
),
|
||||
);
|
||||
},
|
||||
connections: graph.links
|
||||
.filter((l) => [l.source_id, l.sink_id].includes(node.id))
|
||||
.map((link) => ({
|
||||
edge_id: formatEdgeID(link),
|
||||
source: link.source_id,
|
||||
sourceHandle: link.source_name,
|
||||
target: link.sink_id,
|
||||
targetHandle: link.sink_name,
|
||||
})),
|
||||
isOutputOpen: false,
|
||||
setIsAnyModalOpen,
|
||||
setErrors: (errors: { [key: string]: string | null }) => {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) =>
|
||||
node.id === newNode.id
|
||||
? { ...node, data: { ...node.data, errors } }
|
||||
: node,
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
return newNode;
|
||||
});
|
||||
setEdges(
|
||||
graph.links.map(
|
||||
(link) =>
|
||||
({
|
||||
id: formatEdgeID(link),
|
||||
type: "custom",
|
||||
data: {
|
||||
edgeColor: getTypeColor(
|
||||
getOutputType(link.source_id, link.source_name!),
|
||||
),
|
||||
sourcePos: getNode(link.source_id)?.position,
|
||||
isStatic: link.is_static,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
markerEnd: {
|
||||
type: MarkerType.ArrowClosed,
|
||||
strokeWidth: 2,
|
||||
color: getTypeColor(
|
||||
getOutputType(link.source_id, link.source_name!),
|
||||
),
|
||||
},
|
||||
source: link.source_id,
|
||||
target: link.sink_id,
|
||||
sourceHandle: link.source_name || undefined,
|
||||
targetHandle: link.sink_name || undefined,
|
||||
}) as Edge<CustomEdgeData>,
|
||||
),
|
||||
);
|
||||
return newNodes;
|
||||
});
|
||||
}
|
||||
|
||||
const prepareNodeInputData = (node: Node<CustomNodeData>) => {
|
||||
console.log("Preparing input data for node:", node.id, node.data.blockType);
|
||||
|
||||
const blockSchema = availableNodes.find(
|
||||
(n) => n.id === node.data.block_id,
|
||||
)?.inputSchema;
|
||||
|
||||
if (!blockSchema) {
|
||||
console.error(`Schema not found for block ID: ${node.data.block_id}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
const getNestedData = (
|
||||
schema: BlockIOSubSchema,
|
||||
values: { [key: string]: any },
|
||||
): { [key: string]: any } => {
|
||||
let inputData: { [key: string]: any } = {};
|
||||
|
||||
if ("properties" in schema) {
|
||||
Object.keys(schema.properties).forEach((key) => {
|
||||
if (values[key] !== undefined) {
|
||||
if (
|
||||
"properties" in schema.properties[key] ||
|
||||
"additionalProperties" in schema.properties[key]
|
||||
) {
|
||||
inputData[key] = getNestedData(
|
||||
schema.properties[key],
|
||||
values[key],
|
||||
);
|
||||
} else {
|
||||
inputData[key] = values[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ("additionalProperties" in schema) {
|
||||
inputData = { ...inputData, ...values };
|
||||
}
|
||||
|
||||
return inputData;
|
||||
};
|
||||
|
||||
let inputData = getNestedData(blockSchema, node.data.hardcodedValues);
|
||||
|
||||
console.log(
|
||||
`Final prepared input for ${node.data.blockType} (${node.id}):`,
|
||||
inputData,
|
||||
);
|
||||
return inputData;
|
||||
};
|
||||
|
||||
async function saveAgent(asTemplate: boolean = false) {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) => ({
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
node.data.hardcodedValues,
|
||||
),
|
||||
status: undefined,
|
||||
},
|
||||
})),
|
||||
);
|
||||
// Reset bead count
|
||||
setEdges((edges) => {
|
||||
return edges.map(
|
||||
(edge) =>
|
||||
({
|
||||
...edge,
|
||||
data: {
|
||||
...edge.data,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
}) as Edge<CustomEdgeData>,
|
||||
);
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
const nodes = getNodes();
|
||||
const edges = getEdges();
|
||||
console.log("All nodes before formatting:", nodes);
|
||||
const blockIdToNodeIdMap: Record<string, string> = {};
|
||||
|
||||
const formattedNodes = nodes.map((node) => {
|
||||
nodes.forEach((node) => {
|
||||
const key = `${node.data.block_id}_${node.position.x}_${node.position.y}`;
|
||||
blockIdToNodeIdMap[key] = node.id;
|
||||
});
|
||||
const inputDefault = prepareNodeInputData(node);
|
||||
const inputNodes = edges
|
||||
.filter((edge) => edge.target === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.targetHandle || "",
|
||||
node_id: edge.source,
|
||||
}));
|
||||
|
||||
const outputNodes = edges
|
||||
.filter((edge) => edge.source === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.sourceHandle || "",
|
||||
node_id: edge.target,
|
||||
}));
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
block_id: node.data.block_id,
|
||||
input_default: inputDefault,
|
||||
input_nodes: inputNodes,
|
||||
output_nodes: outputNodes,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
node.data.hardcodedValues,
|
||||
),
|
||||
},
|
||||
metadata: { position: node.position },
|
||||
};
|
||||
});
|
||||
|
||||
const links = edges.map((edge) => ({
|
||||
source_id: edge.source,
|
||||
sink_id: edge.target,
|
||||
source_name: edge.sourceHandle || "",
|
||||
sink_name: edge.targetHandle || "",
|
||||
}));
|
||||
|
||||
const payload = {
|
||||
id: savedAgent?.id!,
|
||||
name: agentName || "Agent Name",
|
||||
description: agentDescription || "Agent Description",
|
||||
nodes: formattedNodes,
|
||||
links: links, // Ensure this field is included
|
||||
};
|
||||
|
||||
if (savedAgent && deepEquals(payload, savedAgent)) {
|
||||
console.debug("No need to save: Graph is the same as version on server");
|
||||
return;
|
||||
} else {
|
||||
console.debug(
|
||||
"Saving new Graph version; old vs new:",
|
||||
savedAgent,
|
||||
payload,
|
||||
);
|
||||
}
|
||||
|
||||
const newSavedAgent = savedAgent
|
||||
? await (savedAgent.is_template
|
||||
? api.updateTemplate(savedAgent.id, payload)
|
||||
: api.updateGraph(savedAgent.id, payload))
|
||||
: await (asTemplate
|
||||
? api.createTemplate(payload)
|
||||
: api.createGraph(payload));
|
||||
console.debug("Response from the API:", newSavedAgent);
|
||||
setSavedAgent(newSavedAgent);
|
||||
|
||||
// Update the node IDs in the frontend
|
||||
const updatedNodes = newSavedAgent.nodes
|
||||
.map((backendNode) => {
|
||||
const key = `${backendNode.block_id}_${backendNode.metadata.position.x}_${backendNode.metadata.position.y}`;
|
||||
const frontendNodeId = blockIdToNodeIdMap[key];
|
||||
const frontendNode = nodes.find((node) => node.id === frontendNodeId);
|
||||
|
||||
return frontendNode
|
||||
? {
|
||||
...frontendNode,
|
||||
position: backendNode.metadata.position,
|
||||
data: {
|
||||
...frontendNode.data,
|
||||
backend_id: backendNode.id,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((node) => node !== null);
|
||||
|
||||
setNodes(updatedNodes);
|
||||
|
||||
return newSavedAgent.id;
|
||||
}
|
||||
|
||||
const validateNodes = (): boolean => {
|
||||
let isValid = true;
|
||||
|
||||
getNodes().forEach((node) => {
|
||||
const validate = ajv.compile(node.data.inputSchema);
|
||||
const errors = {} as { [key: string]: string | null };
|
||||
|
||||
// Validate values against schema using AJV
|
||||
const valid = validate(node.data.hardcodedValues);
|
||||
if (!valid) {
|
||||
// Populate errors if validation fails
|
||||
validate.errors?.forEach((error) => {
|
||||
// Skip error if there's an edge connected
|
||||
const path =
|
||||
"dataPath" in error
|
||||
? (error.dataPath as string)
|
||||
: error.instancePath;
|
||||
const handle = path.split(/[\/.]/)[0];
|
||||
if (
|
||||
node.data.connections.some(
|
||||
(conn) => conn.target === node.id || conn.targetHandle === handle,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
isValid = false;
|
||||
if (path && error.message) {
|
||||
const key = path.slice(1);
|
||||
console.log("Error", key, error.message);
|
||||
setNestedProperty(
|
||||
errors,
|
||||
key,
|
||||
error.message[0].toUpperCase() + error.message.slice(1),
|
||||
);
|
||||
} else if (error.keyword === "required") {
|
||||
const key = error.params.missingProperty;
|
||||
setNestedProperty(errors, key, "This field is required");
|
||||
}
|
||||
});
|
||||
}
|
||||
node.data.setErrors(errors);
|
||||
});
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const runAgent = async () => {
|
||||
try {
|
||||
const newAgentId = await saveAgent();
|
||||
if (!newAgentId) {
|
||||
console.error("Error saving agent; aborting run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validateNodes()) {
|
||||
console.error("Validation failed; aborting run");
|
||||
return;
|
||||
}
|
||||
|
||||
api.subscribeToExecution(newAgentId);
|
||||
await api.executeGraph(newAgentId);
|
||||
} catch (error) {
|
||||
console.error("Error running agent:", error);
|
||||
}
|
||||
};
|
||||
|
||||
function getFrontendId(nodeId: string, nodes: Node<CustomNodeData>[]) {
|
||||
const node = nodes.find((node) => node.data.backend_id === nodeId);
|
||||
return node?.id;
|
||||
}
|
||||
|
||||
function updateEdges(
|
||||
executionData: NodeExecutionResult[],
|
||||
nodes: Node<CustomNodeData>[],
|
||||
) {
|
||||
setEdges((edges) => {
|
||||
const newEdges = JSON.parse(
|
||||
JSON.stringify(edges),
|
||||
) as Edge<CustomEdgeData>[];
|
||||
|
||||
executionData.forEach((exec) => {
|
||||
if (exec.status === "COMPLETED") {
|
||||
// Produce output beads
|
||||
for (let key in exec.output_data) {
|
||||
const outputEdges = newEdges.filter(
|
||||
(edge) =>
|
||||
edge.source === getFrontendId(exec.node_id, nodes) &&
|
||||
edge.sourceHandle === key,
|
||||
);
|
||||
outputEdges.forEach((edge) => {
|
||||
edge.data!.beadUp = (edge.data!.beadUp ?? 0) + 1;
|
||||
// For static edges beadDown is always one less than beadUp
|
||||
// Because there's no queueing and one bead is always at the connection point
|
||||
if (edge.data?.isStatic) {
|
||||
edge.data!.beadDown = (edge.data!.beadUp ?? 0) - 1;
|
||||
edge.data!.beadData! = edge.data!.beadData!.slice(0, -1);
|
||||
}
|
||||
//todo kcze this assumes output at key is always array with one element
|
||||
edge.data!.beadData = [
|
||||
exec.output_data[key][0],
|
||||
...edge.data!.beadData!,
|
||||
];
|
||||
});
|
||||
}
|
||||
} else if (exec.status === "RUNNING") {
|
||||
// Consume input beads
|
||||
for (let key in exec.input_data) {
|
||||
const inputEdges = newEdges.filter(
|
||||
(edge) =>
|
||||
edge.target === getFrontendId(exec.node_id, nodes) &&
|
||||
edge.targetHandle === key,
|
||||
);
|
||||
|
||||
inputEdges.forEach((edge) => {
|
||||
// Skip decreasing bead count if edge doesn't match or if it's static
|
||||
if (
|
||||
edge.data!.beadData![edge.data!.beadData!.length - 1] !==
|
||||
exec.input_data[key] ||
|
||||
edge.data?.isStatic
|
||||
) {
|
||||
return;
|
||||
}
|
||||
edge.data!.beadDown = (edge.data!.beadDown ?? 0) + 1;
|
||||
edge.data!.beadData! = edge.data!.beadData!.slice(0, -1);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return newEdges;
|
||||
});
|
||||
}
|
||||
|
||||
const updateNodesWithExecutionData = (
|
||||
executionData: NodeExecutionResult[],
|
||||
) => {
|
||||
console.log("Updating nodes with execution data:", executionData);
|
||||
setNodes((nodes) => {
|
||||
if (visualizeBeads !== "no") {
|
||||
updateEdges(executionData, nodes);
|
||||
}
|
||||
|
||||
const updatedNodes = nodes.map((node) => {
|
||||
const nodeExecution = executionData.find(
|
||||
(exec) => exec.node_id === node.data.backend_id,
|
||||
);
|
||||
|
||||
if (!nodeExecution || node.data.status === nodeExecution.status) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
status: nodeExecution.status,
|
||||
output_data: nodeExecution.output_data,
|
||||
isOutputOpen: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return updatedNodes;
|
||||
});
|
||||
};
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(event: KeyboardEvent) => {
|
||||
if (isAnyModalOpen) return; // Prevent copy/paste if any modal is open
|
||||
@@ -924,8 +383,8 @@ const FlowEditor: React.FC<{
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
if (event.key === "c" || event.key === "C") {
|
||||
// Copy selected nodes
|
||||
const selectedNodes = getNodes().filter((node) => node.selected);
|
||||
const selectedEdges = getEdges().filter((edge) => edge.selected);
|
||||
const selectedNodes = nodes.filter((node) => node.selected);
|
||||
const selectedEdges = edges.filter((edge) => edge.selected);
|
||||
setCopiedNodes(selectedNodes);
|
||||
setCopiedEdges(selectedEdges);
|
||||
}
|
||||
@@ -947,18 +406,6 @@ const FlowEditor: React.FC<{
|
||||
...node.data,
|
||||
status: undefined, // Reset status
|
||||
output_data: undefined, // Clear output data
|
||||
setHardcodedValues: (values: { [key: string]: any }) => {
|
||||
setNodes((nds) =>
|
||||
nds.map((n) =>
|
||||
n.id === newNodeId
|
||||
? {
|
||||
...n,
|
||||
data: { ...n.data, hardcodedValues: values },
|
||||
}
|
||||
: n,
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -987,8 +434,6 @@ const FlowEditor: React.FC<{
|
||||
[
|
||||
addNodes,
|
||||
addEdges,
|
||||
getNodes,
|
||||
getEdges,
|
||||
setNodes,
|
||||
copiedNodes,
|
||||
copiedEdges,
|
||||
@@ -1022,16 +467,18 @@ const FlowEditor: React.FC<{
|
||||
{
|
||||
label: "Run",
|
||||
icon: <IconPlay />,
|
||||
onClick: runAgent,
|
||||
onClick: requestSaveRun,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<FlowContext.Provider value={{ visualizeBeads }}>
|
||||
<FlowContext.Provider value={{ visualizeBeads, setIsAnyModalOpen }}>
|
||||
<div className={className}>
|
||||
<ReactFlow
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
nodeTypes={{ custom: CustomNode }}
|
||||
edgeTypes={{ custom: CustomEdge }}
|
||||
connectionLineComponent={ConnectionLine}
|
||||
onConnect={onConnect}
|
||||
onNodesChange={onNodesChange}
|
||||
@@ -1049,7 +496,7 @@ const FlowEditor: React.FC<{
|
||||
<BlocksControl blocks={availableNodes} addBlock={addNode} />
|
||||
<SaveControl
|
||||
agentMeta={savedAgent}
|
||||
onSave={saveAgent}
|
||||
onSave={(isTemplate) => requestSave(isTemplate ?? false)}
|
||||
onDescriptionChange={setAgentDescription}
|
||||
onNameChange={setAgentName}
|
||||
/>
|
||||
@@ -1067,11 +514,3 @@ const WrappedFlowEditor: typeof FlowEditor = (props) => (
|
||||
);
|
||||
|
||||
export default WrappedFlowEditor;
|
||||
|
||||
function formatEdgeID(conn: Link | Connection): string {
|
||||
if ("sink_id" in conn) {
|
||||
return `${conn.source_id}_${conn.source_name}_${conn.sink_id}_${conn.sink_name}`;
|
||||
} else {
|
||||
return `${conn.source}_${conn.sourceHandle}_${conn.target}_${conn.targetHandle}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BlockIOSubSchema } from "@/lib/autogpt-server-api/types";
|
||||
import { beautifyString, getTypeBgColor, getTypeTextColor } from "@/lib/utils";
|
||||
import { FC } from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
import { Handle, Position } from "@xyflow/react";
|
||||
import SchemaTooltip from "./SchemaTooltip";
|
||||
|
||||
type HandleProps = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// history.ts
|
||||
import { CustomNodeData } from "./CustomNode";
|
||||
import { CustomEdgeData } from "./CustomEdge";
|
||||
import { Edge } from "reactflow";
|
||||
import { Edge } from "@xyflow/react";
|
||||
|
||||
type ActionType =
|
||||
| "ADD_NODE"
|
||||
|
||||
674
rnd/autogpt_builder/src/hooks/useAgentGraph.ts
Normal file
674
rnd/autogpt_builder/src/hooks/useAgentGraph.ts
Normal file
@@ -0,0 +1,674 @@
|
||||
import { CustomEdge } from "@/components/CustomEdge";
|
||||
import { CustomNode } from "@/components/CustomNode";
|
||||
import AutoGPTServerAPI, {
|
||||
Block,
|
||||
BlockIOSubSchema,
|
||||
Graph,
|
||||
Link,
|
||||
NodeExecutionResult,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
import {
|
||||
deepEquals,
|
||||
getTypeColor,
|
||||
removeEmptyStringsAndNulls,
|
||||
setNestedProperty,
|
||||
} from "@/lib/utils";
|
||||
import { Connection, MarkerType } from "@xyflow/react";
|
||||
import Ajv from "ajv";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
const ajv = new Ajv({ strict: false, allErrors: true });
|
||||
|
||||
export default function useAgentGraph(
|
||||
flowID?: string,
|
||||
template?: boolean,
|
||||
passDataToBeads?: boolean,
|
||||
) {
|
||||
const [savedAgent, setSavedAgent] = useState<Graph | null>(null);
|
||||
const [agentDescription, setAgentDescription] = useState<string>("");
|
||||
const [agentName, setAgentName] = useState<string>("");
|
||||
const [availableNodes, setAvailableNodes] = useState<Block[]>([]);
|
||||
const [updateQueue, setUpdateQueue] = useState<NodeExecutionResult[]>([]);
|
||||
const processedUpdates = useRef<NodeExecutionResult[]>([]);
|
||||
/**
|
||||
* User `request` to save or save&run the agent
|
||||
* `state` is used to track the request status:
|
||||
* - none: no request
|
||||
* - saving: request was sent to save the agent
|
||||
* and nodes are pending sync to update their backend ids
|
||||
* - running: request was sent to run the agent
|
||||
* and frontend is enqueueing execution results
|
||||
* - error: request failed
|
||||
*
|
||||
* As of now, state will be stuck at 'running' (if run requested)
|
||||
* because there's no way to know when the execution is done
|
||||
*/
|
||||
const [saveRunRequest, setSaveRunRequest] = useState<{
|
||||
request: "none" | "save" | "run";
|
||||
state: "none" | "saving" | "running" | "error";
|
||||
}>({
|
||||
request: "none",
|
||||
state: "none",
|
||||
});
|
||||
// Determines if nodes backend ids are synced with saved agent (actual ids on the backend)
|
||||
const [nodesSyncedWithSavedAgent, setNodesSyncedWithSavedAgent] =
|
||||
useState(false);
|
||||
const [nodes, setNodes] = useState<CustomNode[]>([]);
|
||||
const [edges, setEdges] = useState<CustomEdge[]>([]);
|
||||
|
||||
const apiUrl = process.env.NEXT_PUBLIC_AGPT_SERVER_URL!;
|
||||
const api = useMemo(() => new AutoGPTServerAPI(apiUrl), [apiUrl]);
|
||||
|
||||
// Connect to WebSocket
|
||||
useEffect(() => {
|
||||
api
|
||||
.connectWebSocket()
|
||||
.then(() => {
|
||||
console.debug("WebSocket connected");
|
||||
api.onWebSocketMessage("execution_event", (data) => {
|
||||
setUpdateQueue((prev) => [...prev, data]);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to connect WebSocket:", error);
|
||||
});
|
||||
|
||||
return () => {
|
||||
api.disconnectWebSocket();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
// Load available blocks
|
||||
useEffect(() => {
|
||||
api
|
||||
.getBlocks()
|
||||
.then((blocks) => setAvailableNodes(blocks))
|
||||
.catch();
|
||||
}, []);
|
||||
|
||||
// Load existing graph
|
||||
useEffect(() => {
|
||||
if (!flowID || availableNodes.length == 0) return;
|
||||
|
||||
(template ? api.getTemplate(flowID) : api.getGraph(flowID)).then((graph) =>
|
||||
loadGraph(graph),
|
||||
);
|
||||
}, [flowID, template, availableNodes]);
|
||||
|
||||
// Update nodes with execution data
|
||||
useEffect(() => {
|
||||
if (updateQueue.length === 0 || !nodesSyncedWithSavedAgent) {
|
||||
return;
|
||||
}
|
||||
setUpdateQueue((prev) => {
|
||||
prev.forEach((data) => {
|
||||
// Skip already processed updates by checking
|
||||
// if the data is in the processedUpdates array by reference
|
||||
// This is not to process twice in react dev mode
|
||||
// because it'll add double the beads
|
||||
if (processedUpdates.current.includes(data)) {
|
||||
return;
|
||||
}
|
||||
updateNodesWithExecutionData(data);
|
||||
processedUpdates.current.push(data);
|
||||
});
|
||||
return [];
|
||||
});
|
||||
}, [updateQueue, nodesSyncedWithSavedAgent]);
|
||||
|
||||
// Handle user requests
|
||||
useEffect(() => {
|
||||
// Ignore none request
|
||||
if (saveRunRequest.request === "none") {
|
||||
return;
|
||||
}
|
||||
// Display error message
|
||||
if (saveRunRequest.state === "error") {
|
||||
if (saveRunRequest.request === "save") {
|
||||
console.error("Error saving agent");
|
||||
} else if (saveRunRequest.request === "run") {
|
||||
console.error(`Error saving&running agent`);
|
||||
}
|
||||
// Reset request
|
||||
setSaveRunRequest((prev) => ({
|
||||
...prev,
|
||||
request: "none",
|
||||
state: "none",
|
||||
}));
|
||||
return;
|
||||
}
|
||||
// When saving request is done
|
||||
if (
|
||||
saveRunRequest.state === "saving" &&
|
||||
savedAgent &&
|
||||
nodesSyncedWithSavedAgent
|
||||
) {
|
||||
// Reset request if only save was requested
|
||||
if (saveRunRequest.request === "save") {
|
||||
setSaveRunRequest((prev) => ({
|
||||
...prev,
|
||||
request: "none",
|
||||
state: "none",
|
||||
}));
|
||||
// If run was requested, run the agent
|
||||
} else if (saveRunRequest.request === "run") {
|
||||
if (!validateNodes()) {
|
||||
console.error("Validation failed; aborting run");
|
||||
setSaveRunRequest({
|
||||
request: "none",
|
||||
state: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
api.subscribeToExecution(savedAgent.id);
|
||||
api.executeGraph(savedAgent.id);
|
||||
processedUpdates.current = processedUpdates.current = [];
|
||||
|
||||
setSaveRunRequest((prev) => ({
|
||||
...prev,
|
||||
request: "run",
|
||||
state: "running",
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, [saveRunRequest, savedAgent, nodesSyncedWithSavedAgent]);
|
||||
|
||||
// Check if node ids are synced with saved agent
|
||||
useEffect(() => {
|
||||
// Check if all node ids are synced with saved agent (frontend and backend)
|
||||
if (!savedAgent || nodes?.length === 0) {
|
||||
setNodesSyncedWithSavedAgent(false);
|
||||
return;
|
||||
}
|
||||
// Find at least one node that has backend id existing on any saved agent node
|
||||
// This will works as long as ALL ids are replaced each time the graph is run
|
||||
const oneNodeSynced = savedAgent.nodes.some(
|
||||
(backendNode) => backendNode.id === nodes[0].data.backend_id,
|
||||
);
|
||||
setNodesSyncedWithSavedAgent(oneNodeSynced);
|
||||
}, [savedAgent, nodes]);
|
||||
|
||||
const validateNodes = useCallback((): boolean => {
|
||||
let isValid = true;
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const validate = ajv.compile(node.data.inputSchema);
|
||||
const errors = {} as { [key: string]: string };
|
||||
|
||||
// Validate values against schema using AJV
|
||||
const valid = validate(node.data.hardcodedValues);
|
||||
if (!valid) {
|
||||
// Populate errors if validation fails
|
||||
validate.errors?.forEach((error) => {
|
||||
// Skip error if there's an edge connected
|
||||
const path =
|
||||
"dataPath" in error
|
||||
? (error.dataPath as string)
|
||||
: error.instancePath;
|
||||
const handle = path.split(/[\/.]/)[0];
|
||||
if (
|
||||
node.data.connections.some(
|
||||
(conn) => conn.target === node.id || conn.targetHandle === handle,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
console.warn("Error", error);
|
||||
isValid = false;
|
||||
if (path && error.message) {
|
||||
const key = path.slice(1);
|
||||
console.log("Error", key, error.message);
|
||||
setNestedProperty(
|
||||
errors,
|
||||
key,
|
||||
error.message[0].toUpperCase() + error.message.slice(1),
|
||||
);
|
||||
} else if (error.keyword === "required") {
|
||||
const key = error.params.missingProperty;
|
||||
setNestedProperty(errors, key, "This field is required");
|
||||
}
|
||||
});
|
||||
}
|
||||
// Set errors
|
||||
setNodes((nodes) => {
|
||||
return nodes.map((n) => {
|
||||
if (n.id === node.id) {
|
||||
return {
|
||||
...n,
|
||||
data: {
|
||||
...n.data,
|
||||
errors,
|
||||
},
|
||||
};
|
||||
}
|
||||
return n;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}, [nodes]);
|
||||
|
||||
const getFrontendId = useCallback(
|
||||
(backendId: string, nodes: CustomNode[]) => {
|
||||
const node = nodes.find((node) => node.data.backend_id === backendId);
|
||||
return node?.id;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const updateEdgeBeads = useCallback(
|
||||
(executionData: NodeExecutionResult) => {
|
||||
setEdges((edges) => {
|
||||
return edges.map((e) => {
|
||||
const edge = { ...e, data: { ...e.data } } as CustomEdge;
|
||||
|
||||
if (executionData.status === "COMPLETED") {
|
||||
// Produce output beads
|
||||
for (let key in executionData.output_data) {
|
||||
if (
|
||||
edge.source !== getFrontendId(executionData.node_id, nodes) ||
|
||||
edge.sourceHandle !== key
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
edge.data!.beadUp = (edge.data!.beadUp ?? 0) + 1;
|
||||
// For static edges beadDown is always one less than beadUp
|
||||
// Because there's no queueing and one bead is always at the connection point
|
||||
if (edge.data?.isStatic) {
|
||||
edge.data!.beadDown = (edge.data!.beadUp ?? 0) - 1;
|
||||
edge.data!.beadData = edge.data!.beadData!.slice(0, -1);
|
||||
continue;
|
||||
}
|
||||
//todo kcze this assumes output at key is always array with one element
|
||||
edge.data!.beadData = [
|
||||
executionData.output_data[key][0],
|
||||
...edge.data!.beadData!,
|
||||
];
|
||||
}
|
||||
} else if (executionData.status === "RUNNING") {
|
||||
// Consume input beads
|
||||
for (let key in executionData.input_data) {
|
||||
if (
|
||||
edge.target !== getFrontendId(executionData.node_id, nodes) ||
|
||||
edge.targetHandle !== key
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
// Skip decreasing bead count if edge doesn't match or if it's static
|
||||
if (
|
||||
edge.data!.beadData![edge.data!.beadData!.length - 1] !==
|
||||
executionData.input_data[key] ||
|
||||
edge.data?.isStatic
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
edge.data!.beadDown = (edge.data!.beadDown ?? 0) + 1;
|
||||
edge.data!.beadData = edge.data!.beadData!.slice(0, -1);
|
||||
}
|
||||
}
|
||||
return edge;
|
||||
});
|
||||
});
|
||||
},
|
||||
[edges],
|
||||
);
|
||||
|
||||
const updateNodesWithExecutionData = useCallback(
|
||||
(executionData: NodeExecutionResult) => {
|
||||
//todo kcze turning off beads
|
||||
if (passDataToBeads) {
|
||||
updateEdgeBeads(executionData);
|
||||
}
|
||||
setNodes((nodes) => {
|
||||
const nodeId = nodes.find(
|
||||
(node) => node.data.backend_id === executionData.node_id,
|
||||
)?.id;
|
||||
if (!nodeId) {
|
||||
console.error(
|
||||
"Node not found for execution data:",
|
||||
executionData,
|
||||
"This shouldn't happen and means that the frontend and backend are out of sync.",
|
||||
);
|
||||
return nodes;
|
||||
}
|
||||
return nodes.map((node) =>
|
||||
node.id === nodeId
|
||||
? {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
status: executionData.status,
|
||||
output_data: executionData.output_data,
|
||||
isOutputOpen: true,
|
||||
},
|
||||
}
|
||||
: node,
|
||||
);
|
||||
});
|
||||
},
|
||||
[nodes],
|
||||
);
|
||||
|
||||
//kcze to utils? repeated in Flow
|
||||
const formatEdgeID = useCallback((conn: Link | Connection): string => {
|
||||
if ("sink_id" in conn) {
|
||||
return `${conn.source_id}_${conn.source_name}_${conn.sink_id}_${conn.sink_name}`;
|
||||
} else {
|
||||
return `${conn.source}_${conn.sourceHandle}_${conn.target}_${conn.targetHandle}`;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getOutputType = useCallback(
|
||||
(nodeId: string, handleId: string) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
if (!node) return "unknown";
|
||||
|
||||
const outputSchema = node.data.outputSchema;
|
||||
if (!outputSchema) return "unknown";
|
||||
|
||||
const outputHandle = outputSchema.properties[handleId];
|
||||
if (!("type" in outputHandle)) return "unknown";
|
||||
return outputHandle.type;
|
||||
},
|
||||
[nodes],
|
||||
);
|
||||
|
||||
const loadGraph = useCallback(
|
||||
(graph: Graph) => {
|
||||
setSavedAgent(graph);
|
||||
setAgentName(graph.name);
|
||||
setAgentDescription(graph.description);
|
||||
|
||||
setNodes(() => {
|
||||
const newNodes = graph.nodes.map((node) => {
|
||||
const block = availableNodes.find(
|
||||
(block) => block.id === node.block_id,
|
||||
)!;
|
||||
const newNode: CustomNode = {
|
||||
id: node.id,
|
||||
type: "custom",
|
||||
position: {
|
||||
x: node.metadata.position.x,
|
||||
y: node.metadata.position.y,
|
||||
},
|
||||
data: {
|
||||
block_id: block.id,
|
||||
blockType: block.name,
|
||||
categories: block.categories,
|
||||
description: block.description,
|
||||
title: `${block.name} ${node.id}`,
|
||||
inputSchema: block.inputSchema,
|
||||
outputSchema: block.outputSchema,
|
||||
hardcodedValues: node.input_default,
|
||||
connections: graph.links
|
||||
.filter((l) => [l.source_id, l.sink_id].includes(node.id))
|
||||
.map((link) => ({
|
||||
edge_id: formatEdgeID(link),
|
||||
source: link.source_id,
|
||||
sourceHandle: link.source_name,
|
||||
target: link.sink_id,
|
||||
targetHandle: link.sink_name,
|
||||
})),
|
||||
isOutputOpen: false,
|
||||
},
|
||||
};
|
||||
return newNode;
|
||||
});
|
||||
setEdges((_) =>
|
||||
graph.links.map((link) => ({
|
||||
id: formatEdgeID(link),
|
||||
type: "custom",
|
||||
data: {
|
||||
edgeColor: getTypeColor(
|
||||
getOutputType(link.source_id, link.source_name!),
|
||||
),
|
||||
sourcePos: nodes.find((node) => node.id === link.source_id)
|
||||
?.position,
|
||||
isStatic: link.is_static,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
markerEnd: {
|
||||
type: MarkerType.ArrowClosed,
|
||||
strokeWidth: 2,
|
||||
color: getTypeColor(
|
||||
getOutputType(link.source_id, link.source_name!),
|
||||
),
|
||||
},
|
||||
source: link.source_id,
|
||||
target: link.sink_id,
|
||||
sourceHandle: link.source_name || undefined,
|
||||
targetHandle: link.sink_name || undefined,
|
||||
})),
|
||||
);
|
||||
return newNodes;
|
||||
});
|
||||
},
|
||||
[availableNodes],
|
||||
);
|
||||
|
||||
const prepareNodeInputData = useCallback(
|
||||
(node: CustomNode) => {
|
||||
console.debug(
|
||||
"Preparing input data for node:",
|
||||
node.id,
|
||||
node.data.blockType,
|
||||
);
|
||||
|
||||
const blockSchema = availableNodes.find(
|
||||
(n) => n.id === node.data.block_id,
|
||||
)?.inputSchema;
|
||||
|
||||
if (!blockSchema) {
|
||||
console.error(`Schema not found for block ID: ${node.data.block_id}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
const getNestedData = (
|
||||
schema: BlockIOSubSchema,
|
||||
values: { [key: string]: any },
|
||||
): { [key: string]: any } => {
|
||||
let inputData: { [key: string]: any } = {};
|
||||
|
||||
if ("properties" in schema) {
|
||||
Object.keys(schema.properties).forEach((key) => {
|
||||
if (values[key] !== undefined) {
|
||||
if (
|
||||
"properties" in schema.properties[key] ||
|
||||
"additionalProperties" in schema.properties[key]
|
||||
) {
|
||||
inputData[key] = getNestedData(
|
||||
schema.properties[key],
|
||||
values[key],
|
||||
);
|
||||
} else {
|
||||
inputData[key] = values[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ("additionalProperties" in schema) {
|
||||
inputData = { ...inputData, ...values };
|
||||
}
|
||||
|
||||
return inputData;
|
||||
};
|
||||
|
||||
let inputData = getNestedData(blockSchema, node.data.hardcodedValues);
|
||||
|
||||
console.debug(
|
||||
`Final prepared input for ${node.data.blockType} (${node.id}):`,
|
||||
inputData,
|
||||
);
|
||||
return inputData;
|
||||
},
|
||||
[availableNodes],
|
||||
);
|
||||
|
||||
const saveAgent = useCallback(
|
||||
async (asTemplate: boolean = false) => {
|
||||
//FIXME frontend ids should be resolved better (e.g. returned from the server)
|
||||
// currently this relays on block_id and position
|
||||
const blockIdToNodeIdMap: Record<string, string> = {};
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const key = `${node.data.block_id}_${node.position.x}_${node.position.y}`;
|
||||
blockIdToNodeIdMap[key] = node.id;
|
||||
});
|
||||
|
||||
const formattedNodes = nodes.map((node) => {
|
||||
const inputDefault = prepareNodeInputData(node);
|
||||
const inputNodes = edges
|
||||
.filter((edge) => edge.target === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.targetHandle || "",
|
||||
node_id: edge.source,
|
||||
}));
|
||||
|
||||
const outputNodes = edges
|
||||
.filter((edge) => edge.source === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.sourceHandle || "",
|
||||
node_id: edge.target,
|
||||
}));
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
block_id: node.data.block_id,
|
||||
input_default: inputDefault,
|
||||
input_nodes: inputNodes,
|
||||
output_nodes: outputNodes,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
node.data.hardcodedValues,
|
||||
),
|
||||
},
|
||||
metadata: { position: node.position },
|
||||
};
|
||||
});
|
||||
|
||||
const links = edges.map((edge) => ({
|
||||
source_id: edge.source,
|
||||
sink_id: edge.target,
|
||||
source_name: edge.sourceHandle || "",
|
||||
sink_name: edge.targetHandle || "",
|
||||
}));
|
||||
|
||||
const payload = {
|
||||
id: savedAgent?.id!,
|
||||
name: agentName || "Agent Name",
|
||||
description: agentDescription || "Agent Description",
|
||||
nodes: formattedNodes,
|
||||
links: links,
|
||||
};
|
||||
|
||||
if (savedAgent && deepEquals(payload, savedAgent)) {
|
||||
console.debug(
|
||||
"No need to save: Graph is the same as version on server",
|
||||
);
|
||||
// Trigger state change
|
||||
setSavedAgent(savedAgent);
|
||||
return;
|
||||
} else {
|
||||
console.debug(
|
||||
"Saving new Graph version; old vs new:",
|
||||
savedAgent,
|
||||
payload,
|
||||
);
|
||||
}
|
||||
|
||||
setNodesSyncedWithSavedAgent(false);
|
||||
|
||||
const newSavedAgent = savedAgent
|
||||
? await (savedAgent.is_template
|
||||
? api.updateTemplate(savedAgent.id, payload)
|
||||
: api.updateGraph(savedAgent.id, payload))
|
||||
: await (asTemplate
|
||||
? api.createTemplate(payload)
|
||||
: api.createGraph(payload));
|
||||
console.debug("Response from the API:", newSavedAgent);
|
||||
|
||||
// Update the node IDs on the frontend
|
||||
setSavedAgent(newSavedAgent);
|
||||
setNodes((prev) => {
|
||||
return newSavedAgent.nodes
|
||||
.map((backendNode) => {
|
||||
const key = `${backendNode.block_id}_${backendNode.metadata.position.x}_${backendNode.metadata.position.y}`;
|
||||
const frontendNodeId = blockIdToNodeIdMap[key];
|
||||
const frontendNode = prev.find(
|
||||
(node) => node.id === frontendNodeId,
|
||||
);
|
||||
|
||||
return frontendNode
|
||||
? {
|
||||
...frontendNode,
|
||||
position: backendNode.metadata.position,
|
||||
data: {
|
||||
...frontendNode.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
frontendNode.data.hardcodedValues,
|
||||
),
|
||||
status: undefined,
|
||||
backend_id: backendNode.id,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((node) => node !== null);
|
||||
});
|
||||
// Reset bead count
|
||||
setEdges((edges) => {
|
||||
return edges.map((edge) => ({
|
||||
...edge,
|
||||
data: {
|
||||
...edge.data,
|
||||
edgeColor: edge.data?.edgeColor!,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
}));
|
||||
});
|
||||
},
|
||||
[nodes, edges, savedAgent],
|
||||
);
|
||||
|
||||
const requestSave = useCallback(
|
||||
(asTemplate: boolean) => {
|
||||
saveAgent(asTemplate);
|
||||
setSaveRunRequest({
|
||||
request: "save",
|
||||
state: "saving",
|
||||
});
|
||||
},
|
||||
[saveAgent],
|
||||
);
|
||||
|
||||
const requestSaveRun = useCallback(() => {
|
||||
saveAgent();
|
||||
setSaveRunRequest({
|
||||
request: "run",
|
||||
state: "saving",
|
||||
});
|
||||
}, [saveAgent]);
|
||||
|
||||
return {
|
||||
agentName,
|
||||
setAgentName,
|
||||
agentDescription,
|
||||
setAgentDescription,
|
||||
savedAgent,
|
||||
availableNodes,
|
||||
getOutputType,
|
||||
requestSave,
|
||||
requestSaveRun,
|
||||
nodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
};
|
||||
}
|
||||
@@ -190,12 +190,12 @@ export default class AutoGPTServerAPI {
|
||||
this.webSocket = new WebSocket(wsUrlWithToken);
|
||||
|
||||
this.webSocket.onopen = () => {
|
||||
console.log("WebSocket connection established");
|
||||
console.debug("WebSocket connection established");
|
||||
resolve();
|
||||
};
|
||||
|
||||
this.webSocket.onclose = (event) => {
|
||||
console.log("WebSocket connection closed", event);
|
||||
console.debug("WebSocket connection closed", event);
|
||||
this.webSocket = null;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ type BlockIOSimpleTypeSubSchema =
|
||||
| BlockIOBooleanSubSchema
|
||||
| BlockIONullSubSchema;
|
||||
|
||||
type BlockIOSubSchemaMeta = {
|
||||
export type BlockIOSubSchemaMeta = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
placeholder?: string;
|
||||
@@ -121,7 +121,7 @@ export type Link = {
|
||||
is_static: boolean;
|
||||
};
|
||||
|
||||
export type LinkCreatable = Omit<Link, "id"> & {
|
||||
export type LinkCreatable = Omit<Link, "id" | "is_static"> & {
|
||||
id?: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -158,6 +158,46 @@
|
||||
resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz"
|
||||
integrity sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==
|
||||
|
||||
"@next/swc-darwin-x64@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz#46dedb29ec5503bf171a72a3ecb8aac6e738e9d6"
|
||||
integrity sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz#c9697ab9eb422bd1d7ffd0eb0779cc2aefa9d4a1"
|
||||
integrity sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==
|
||||
|
||||
"@next/swc-linux-arm64-musl@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz#cbbceb2008571c743b5a310a488d2e166d200a75"
|
||||
integrity sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==
|
||||
|
||||
"@next/swc-linux-x64-gnu@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz#d79184223f857bacffb92f643cb2943a43632568"
|
||||
integrity sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==
|
||||
|
||||
"@next/swc-linux-x64-musl@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz#6b6c3e5ac02ca5e63394d280ec8ee607491902df"
|
||||
integrity sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz#dbad3906e870dba84c5883d9d4c4838472e0697f"
|
||||
integrity sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz#6074529b91ba49132922ce89a2e16d25d2ec235d"
|
||||
integrity sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==
|
||||
|
||||
"@next/swc-win32-x64-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz#e65a1c6539a671f97bb86d5183d6e3a1733c29c7"
|
||||
integrity sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==
|
||||
|
||||
"@next/third-parties@^14.2.5":
|
||||
version "14.2.6"
|
||||
resolved "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.2.6.tgz"
|
||||
@@ -173,7 +213,7 @@
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
@@ -287,26 +327,6 @@
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz"
|
||||
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
|
||||
|
||||
"@radix-ui/react-dialog@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz"
|
||||
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.0"
|
||||
"@radix-ui/react-focus-guards" "1.1.0"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-portal" "1.1.1"
|
||||
"@radix-ui/react-presence" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.7"
|
||||
|
||||
"@radix-ui/react-dialog@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz"
|
||||
@@ -328,6 +348,26 @@
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.5"
|
||||
|
||||
"@radix-ui/react-dialog@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz"
|
||||
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.0"
|
||||
"@radix-ui/react-focus-guards" "1.1.0"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-portal" "1.1.1"
|
||||
"@radix-ui/react-presence" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.7"
|
||||
|
||||
"@radix-ui/react-direction@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz"
|
||||
@@ -600,13 +640,6 @@
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
|
||||
"@radix-ui/react-slot@^1.1.0", "@radix-ui/react-slot@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz"
|
||||
integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
|
||||
"@radix-ui/react-slot@1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz"
|
||||
@@ -615,6 +648,13 @@
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "1.0.1"
|
||||
|
||||
"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz"
|
||||
integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
|
||||
"@radix-ui/react-switch@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.0.tgz"
|
||||
@@ -731,71 +771,10 @@
|
||||
resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz"
|
||||
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
|
||||
|
||||
"@reactflow/background@11.3.14":
|
||||
version "11.3.14"
|
||||
resolved "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz"
|
||||
integrity sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/controls@11.2.14":
|
||||
version "11.2.14"
|
||||
resolved "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.14.tgz"
|
||||
integrity sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/core@11.11.4":
|
||||
version "11.11.4"
|
||||
resolved "https://registry.npmjs.org/@reactflow/core/-/core-11.11.4.tgz"
|
||||
integrity sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==
|
||||
dependencies:
|
||||
"@types/d3" "^7.4.0"
|
||||
"@types/d3-drag" "^3.0.1"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/minimap@11.7.14":
|
||||
version "11.7.14"
|
||||
resolved "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.14.tgz"
|
||||
integrity sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-resizer@2.2.14":
|
||||
version "2.2.14"
|
||||
resolved "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.14.tgz"
|
||||
integrity sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.4"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-toolbar@1.3.14":
|
||||
version "1.3.14"
|
||||
resolved "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.14.tgz"
|
||||
integrity sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
"@rollup/rollup-linux-x64-gnu@^4.9.5":
|
||||
version "4.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz#4fd36a6a41f3406d8693321b13d4f9b7658dd4b9"
|
||||
integrity sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==
|
||||
|
||||
"@rushstack/eslint-patch@^1.3.3":
|
||||
version "1.10.4"
|
||||
@@ -816,7 +795,7 @@
|
||||
dependencies:
|
||||
"@supabase/node-fetch" "^2.6.14"
|
||||
|
||||
"@supabase/node-fetch@^2.6.14", "@supabase/node-fetch@2.6.15":
|
||||
"@supabase/node-fetch@2.6.15", "@supabase/node-fetch@^2.6.14":
|
||||
version "2.6.15"
|
||||
resolved "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz"
|
||||
integrity sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==
|
||||
@@ -856,7 +835,7 @@
|
||||
dependencies:
|
||||
"@supabase/node-fetch" "^2.6.14"
|
||||
|
||||
"@supabase/supabase-js@^2.43.4", "@supabase/supabase-js@^2.45.0":
|
||||
"@supabase/supabase-js@^2.45.0":
|
||||
version "2.45.0"
|
||||
resolved "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.45.0.tgz"
|
||||
integrity sha512-j66Mfs8RhzCQCKxKogAFQYH9oNhRmgIdKk6pexguI2Oc7hi+nL9UNJug5aL1tKnBdaBM3h65riPLQSdL6sWa3Q==
|
||||
@@ -881,99 +860,28 @@
|
||||
"@swc/counter" "^0.1.3"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@types/d3-array@*", "@types/d3-array@^3.0.3":
|
||||
"@types/d3-array@^3.0.3":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz"
|
||||
integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
|
||||
|
||||
"@types/d3-axis@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz"
|
||||
integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-brush@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz"
|
||||
integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-chord@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz"
|
||||
integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==
|
||||
|
||||
"@types/d3-color@*":
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz"
|
||||
integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
|
||||
|
||||
"@types/d3-contour@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz"
|
||||
integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-delaunay@*":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz"
|
||||
integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==
|
||||
|
||||
"@types/d3-dispatch@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz"
|
||||
integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==
|
||||
|
||||
"@types/d3-drag@*", "@types/d3-drag@^3.0.1":
|
||||
"@types/d3-drag@^3.0.7":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02"
|
||||
integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-dsv@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz"
|
||||
integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==
|
||||
|
||||
"@types/d3-ease@*", "@types/d3-ease@^3.0.0":
|
||||
"@types/d3-ease@^3.0.0":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz"
|
||||
integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
|
||||
|
||||
"@types/d3-fetch@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz"
|
||||
integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==
|
||||
dependencies:
|
||||
"@types/d3-dsv" "*"
|
||||
|
||||
"@types/d3-force@*":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz"
|
||||
integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==
|
||||
|
||||
"@types/d3-format@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz"
|
||||
integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==
|
||||
|
||||
"@types/d3-geo@*":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz"
|
||||
integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==
|
||||
dependencies:
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-hierarchy@*":
|
||||
version "3.1.7"
|
||||
resolved "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz"
|
||||
integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==
|
||||
|
||||
"@types/d3-interpolate@*", "@types/d3-interpolate@^3.0.1":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz"
|
||||
@@ -986,111 +894,50 @@
|
||||
resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz"
|
||||
integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==
|
||||
|
||||
"@types/d3-polygon@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz"
|
||||
integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==
|
||||
|
||||
"@types/d3-quadtree@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz"
|
||||
integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==
|
||||
|
||||
"@types/d3-random@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz"
|
||||
integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==
|
||||
|
||||
"@types/d3-scale-chromatic@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz"
|
||||
integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==
|
||||
|
||||
"@types/d3-scale@*", "@types/d3-scale@^4.0.2":
|
||||
"@types/d3-scale@^4.0.2":
|
||||
version "4.0.8"
|
||||
resolved "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz"
|
||||
integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==
|
||||
dependencies:
|
||||
"@types/d3-time" "*"
|
||||
|
||||
"@types/d3-selection@*", "@types/d3-selection@^3.0.3":
|
||||
"@types/d3-selection@*", "@types/d3-selection@^3.0.10":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe"
|
||||
integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==
|
||||
|
||||
"@types/d3-shape@*", "@types/d3-shape@^3.1.0":
|
||||
"@types/d3-shape@^3.1.0":
|
||||
version "3.1.6"
|
||||
resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz"
|
||||
integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==
|
||||
dependencies:
|
||||
"@types/d3-path" "*"
|
||||
|
||||
"@types/d3-time-format@*":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz"
|
||||
integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==
|
||||
|
||||
"@types/d3-time@*", "@types/d3-time@^3.0.0":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz"
|
||||
integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==
|
||||
|
||||
"@types/d3-timer@*", "@types/d3-timer@^3.0.0":
|
||||
"@types/d3-timer@^3.0.0":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz"
|
||||
integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
|
||||
|
||||
"@types/d3-transition@*":
|
||||
"@types/d3-transition@^3.0.8":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f"
|
||||
integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-zoom@*", "@types/d3-zoom@^3.0.1":
|
||||
"@types/d3-zoom@^3.0.8":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b"
|
||||
integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==
|
||||
dependencies:
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3@^7.4.0":
|
||||
version "7.4.3"
|
||||
resolved "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz"
|
||||
integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/d3-axis" "*"
|
||||
"@types/d3-brush" "*"
|
||||
"@types/d3-chord" "*"
|
||||
"@types/d3-color" "*"
|
||||
"@types/d3-contour" "*"
|
||||
"@types/d3-delaunay" "*"
|
||||
"@types/d3-dispatch" "*"
|
||||
"@types/d3-drag" "*"
|
||||
"@types/d3-dsv" "*"
|
||||
"@types/d3-ease" "*"
|
||||
"@types/d3-fetch" "*"
|
||||
"@types/d3-force" "*"
|
||||
"@types/d3-format" "*"
|
||||
"@types/d3-geo" "*"
|
||||
"@types/d3-hierarchy" "*"
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-path" "*"
|
||||
"@types/d3-polygon" "*"
|
||||
"@types/d3-quadtree" "*"
|
||||
"@types/d3-random" "*"
|
||||
"@types/d3-scale" "*"
|
||||
"@types/d3-scale-chromatic" "*"
|
||||
"@types/d3-selection" "*"
|
||||
"@types/d3-shape" "*"
|
||||
"@types/d3-time" "*"
|
||||
"@types/d3-time-format" "*"
|
||||
"@types/d3-timer" "*"
|
||||
"@types/d3-transition" "*"
|
||||
"@types/d3-zoom" "*"
|
||||
|
||||
"@types/debug@^4.0.0":
|
||||
version "4.1.12"
|
||||
resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz"
|
||||
@@ -1110,11 +957,6 @@
|
||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/geojson@*":
|
||||
version "7946.0.14"
|
||||
resolved "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz"
|
||||
integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==
|
||||
|
||||
"@types/hast@^3.0.0":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz"
|
||||
@@ -1156,7 +998,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz"
|
||||
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
|
||||
|
||||
"@types/react-dom@*", "@types/react-dom@^18":
|
||||
"@types/react-dom@^18":
|
||||
version "18.3.0"
|
||||
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz"
|
||||
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
|
||||
@@ -1170,7 +1012,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^18", "@types/react@>=16.8", "@types/react@>=18":
|
||||
"@types/react@*", "@types/react@^18":
|
||||
version "18.3.3"
|
||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz"
|
||||
integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==
|
||||
@@ -1246,12 +1088,34 @@
|
||||
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz"
|
||||
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
|
||||
|
||||
"@xyflow/react@^12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@xyflow/react/-/react-12.1.0.tgz#71a93eb514497b0ae3835b45df21ac14ce6e0812"
|
||||
integrity sha512-tlYBV8S27kTwLuKvKa3dX0yEJ6NgUup9BwXLWcdNKdZq+UvLfDr5JXHwzyRqT1XSlYFv+YgcfroGmir8krYXIg==
|
||||
dependencies:
|
||||
"@xyflow/system" "0.0.38"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.0"
|
||||
|
||||
"@xyflow/system@0.0.38":
|
||||
version "0.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@xyflow/system/-/system-0.0.38.tgz#4bf67fa1adfba5cd3760d182ce645841fc652c69"
|
||||
integrity sha512-auJU8djbT59S5Afb9lFds1lQJvKIb0zUoHhO+il/ogDDG5BbFds6D8g5a8Q3oHdyR6dy0TaD1oZq9s7Ydhn41g==
|
||||
dependencies:
|
||||
"@types/d3-drag" "^3.0.7"
|
||||
"@types/d3-selection" "^3.0.10"
|
||||
"@types/d3-transition" "^3.0.8"
|
||||
"@types/d3-zoom" "^3.0.8"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
|
||||
acorn-jsx@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0:
|
||||
acorn@^8.9.0:
|
||||
version "8.12.1"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz"
|
||||
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
|
||||
@@ -1578,7 +1442,7 @@ class-variance-authority@^0.7.0:
|
||||
dependencies:
|
||||
clsx "2.0.0"
|
||||
|
||||
classcat@^5.0.3, classcat@^5.0.4:
|
||||
classcat@^5.0.3:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz"
|
||||
integrity sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==
|
||||
@@ -1588,16 +1452,16 @@ client-only@0.0.1:
|
||||
resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz"
|
||||
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||
|
||||
clsx@^2.0.0, clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
clsx@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz"
|
||||
integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
|
||||
|
||||
clsx@^2.0.0, clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
cmdk@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz"
|
||||
@@ -1657,7 +1521,7 @@ csstype@^3.0.2:
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||
|
||||
d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
|
||||
"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz"
|
||||
integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
|
||||
@@ -1674,7 +1538,7 @@ d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
|
||||
resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz"
|
||||
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||
|
||||
d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
"d3-drag@2 - 3", d3-drag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz"
|
||||
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||
@@ -1682,7 +1546,7 @@ d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
d3-dispatch "1 - 3"
|
||||
d3-selection "3"
|
||||
|
||||
d3-ease@^3.0.1, "d3-ease@1 - 3":
|
||||
"d3-ease@1 - 3", d3-ease@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz"
|
||||
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
|
||||
@@ -1692,7 +1556,7 @@ d3-ease@^3.0.1, "d3-ease@1 - 3":
|
||||
resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz"
|
||||
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
|
||||
|
||||
d3-interpolate@^3.0.1, "d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3":
|
||||
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz"
|
||||
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||
@@ -1715,7 +1579,7 @@ d3-scale@^4.0.2:
|
||||
d3-time "2.1.1 - 3"
|
||||
d3-time-format "2 - 4"
|
||||
|
||||
d3-selection@^3.0.0, "d3-selection@2 - 3", d3-selection@3:
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz"
|
||||
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||
@@ -1734,14 +1598,14 @@ d3-shape@^3.1.0:
|
||||
dependencies:
|
||||
d3-time "1 - 3"
|
||||
|
||||
d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3":
|
||||
"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz"
|
||||
integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
|
||||
dependencies:
|
||||
d3-array "2 - 3"
|
||||
|
||||
d3-timer@^3.0.1, "d3-timer@1 - 3":
|
||||
"d3-timer@1 - 3", d3-timer@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz"
|
||||
integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
|
||||
@@ -1800,7 +1664,7 @@ data-view-byte-offset@^1.0.0:
|
||||
es-errors "^1.3.0"
|
||||
is-data-view "^1.0.1"
|
||||
|
||||
"date-fns@^2.28.0 || ^3.0.0", date-fns@^3.6.0:
|
||||
date-fns@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
|
||||
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
|
||||
@@ -2142,7 +2006,7 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
|
||||
dependencies:
|
||||
debug "^3.2.7"
|
||||
|
||||
eslint-plugin-import@*, eslint-plugin-import@^2.28.1:
|
||||
eslint-plugin-import@^2.28.1:
|
||||
version "2.29.1"
|
||||
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz"
|
||||
integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
|
||||
@@ -2229,7 +2093,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.23.0 || ^8.0.0", eslint@^8, eslint@^8.56.0:
|
||||
eslint@^8:
|
||||
version "8.57.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz"
|
||||
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
|
||||
@@ -2482,7 +2346,7 @@ get-tsconfig@^4.5.0:
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
glob-parent@^5.1.2:
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
@@ -2496,14 +2360,7 @@ glob-parent@^6.0.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^10.3.10, glob@10.3.10:
|
||||
glob@10.3.10, glob@^10.3.10:
|
||||
version "10.3.10"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz"
|
||||
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
|
||||
@@ -3396,6 +3253,13 @@ micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||
@@ -3410,13 +3274,6 @@ minimatch@^9.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
||||
@@ -3432,7 +3289,7 @@ moment@^2.30.1:
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz"
|
||||
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
|
||||
|
||||
ms@^2.1.1, ms@2.1.2:
|
||||
ms@2.1.2, ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
@@ -3461,7 +3318,7 @@ next-themes@^0.3.0:
|
||||
resolved "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz"
|
||||
integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==
|
||||
|
||||
"next@^13.0.0 || ^14.0.0", next@14.2.4:
|
||||
next@14.2.4:
|
||||
version "14.2.4"
|
||||
resolved "https://registry.npmjs.org/next/-/next-14.2.4.tgz"
|
||||
integrity sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==
|
||||
@@ -3720,15 +3577,6 @@ postcss-value-parser@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8, postcss@^8.0.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9:
|
||||
version "8.4.38"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz"
|
||||
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
|
||||
dependencies:
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
postcss@8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz"
|
||||
@@ -3738,6 +3586,15 @@ postcss@8.4.31:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8, postcss@^8.4.23:
|
||||
version "8.4.38"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz"
|
||||
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
|
||||
dependencies:
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||
@@ -3748,7 +3605,7 @@ prettier-plugin-tailwindcss@^0.6.6:
|
||||
resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.6.tgz"
|
||||
integrity sha512-OPva5S7WAsPLEsOuOWXATi13QrCKACCiIonFgIR6V4lYv4QLp++UXVhZSzRbZxXGimkQtQT86CC6fQqTOybGng==
|
||||
|
||||
prettier@^3.0, prettier@^3.3.3:
|
||||
prettier@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
@@ -3782,7 +3639,7 @@ react-day-picker@^8.10.1:
|
||||
resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz"
|
||||
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
||||
|
||||
"react-dom@^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8 || ^17 || ^18", "react-dom@^16.8 || ^17.0 || ^18.0", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", react-dom@^18, react-dom@^18.0.0, react-dom@^18.2.0, react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=17:
|
||||
react-dom@^18:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
|
||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||
@@ -3790,7 +3647,7 @@ react-day-picker@^8.10.1:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.2"
|
||||
|
||||
react-hook-form@^7.0.0, react-hook-form@^7.52.1:
|
||||
react-hook-form@^7.52.1:
|
||||
version "7.52.1"
|
||||
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.1.tgz"
|
||||
integrity sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==
|
||||
@@ -3894,25 +3751,13 @@ react-transition-group@^4.4.5:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react@*, "react@^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", "react@^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17 || ^18", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.x || ^17.x || ^18.x", react@^18, react@^18.0.0, react@^18.2.0, react@^18.3.1, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=17, react@>=18:
|
||||
react@^18:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
reactflow@^11.11.4:
|
||||
version "11.11.4"
|
||||
resolved "https://registry.npmjs.org/reactflow/-/reactflow-11.11.4.tgz"
|
||||
integrity sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==
|
||||
dependencies:
|
||||
"@reactflow/background" "11.3.14"
|
||||
"@reactflow/controls" "11.2.14"
|
||||
"@reactflow/core" "11.11.4"
|
||||
"@reactflow/minimap" "11.7.14"
|
||||
"@reactflow/node-resizer" "2.2.14"
|
||||
"@reactflow/node-toolbar" "1.3.14"
|
||||
|
||||
read-cache@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz"
|
||||
@@ -4340,7 +4185,7 @@ tailwindcss-animate@^1.0.7:
|
||||
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
|
||||
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
|
||||
|
||||
tailwindcss@^3.4.1, "tailwindcss@>=3.0.0 || insiders":
|
||||
tailwindcss@^3.4.1:
|
||||
version "3.4.4"
|
||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz"
|
||||
integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==
|
||||
@@ -4505,7 +4350,7 @@ typed-array-length@^1.0.6:
|
||||
is-typed-array "^1.1.13"
|
||||
possible-typed-array-names "^1.0.0"
|
||||
|
||||
typescript@^5, typescript@>=3.3.1, typescript@>=4.2.0:
|
||||
typescript@^5:
|
||||
version "5.5.2"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz"
|
||||
integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==
|
||||
@@ -4606,10 +4451,10 @@ use-sidecar@^1.1.2:
|
||||
detect-node-es "^1.1.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
use-sync-external-store@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
use-sync-external-store@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9"
|
||||
integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==
|
||||
|
||||
util-deprecate@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -4778,12 +4623,12 @@ zod@^3.23.8:
|
||||
resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
||||
zustand@^4.4.1:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.npmjs.org/zustand/-/zustand-4.5.4.tgz"
|
||||
integrity sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==
|
||||
zustand@^4.4.0:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.5.tgz#f8c713041543715ec81a2adda0610e1dc82d4ad1"
|
||||
integrity sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==
|
||||
dependencies:
|
||||
use-sync-external-store "1.2.0"
|
||||
use-sync-external-store "1.2.2"
|
||||
|
||||
zwitch@^2.0.0:
|
||||
version "2.0.4"
|
||||
|
||||
Reference in New Issue
Block a user