diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index a4eae7f21..913822bd3 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -1,8 +1,4 @@ -import { - useEffect, - useRef, - useState, -} from "react"; +import { useEffect, useRef, useState } from "react"; import { ChatMessageType, ChatType } from "../../types/chat"; import ChatTrigger from "./chatTrigger"; @@ -11,23 +7,26 @@ import ChatModal from "../../modals/chatModal"; const _ = require("lodash"); export default function Chat({ flow }: ChatType) { - const [open, setOpen] = useState(false); - useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - event.preventDefault() - if ((event.key === "K"||event.key==="k") && (event.metaKey||event.ctrlKey)) { - setOpen(oldState=>!oldState); - } - }; - document.addEventListener("keydown", handleKeyDown); - return () => { - document.removeEventListener("keydown", handleKeyDown); - }; - }, []); - return ( - <> - - - - ); + const [open, setOpen] = useState(false); + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + // event.preventDefault() + if ( + (event.key === "K" || event.key === "k") && + (event.metaKey || event.ctrlKey) + ) { + setOpen((oldState) => !oldState); + } + }; + document.addEventListener("keydown", handleKeyDown); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + return ( + <> + + + + ); } diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 490ec2837..f6f46404b 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -1,40 +1,43 @@ -import { PromptTypeAPI, errorsTypeAPI } from './../../types/api/index'; -import { APIObjectType, sendAllProps } from '../../types/api/index'; +import { PromptTypeAPI, errorsTypeAPI } from "./../../types/api/index"; +import { APIObjectType, sendAllProps } from "../../types/api/index"; import axios, { AxiosResponse } from "axios"; -import { FlowType } from '../../types/flow'; +import { FlowType } from "../../types/flow"; -export async function getAll():Promise> { - return await axios.get(`/all`); +export async function getAll(): Promise> { + return await axios.get(`/all`); } -export async function sendAll(data:sendAllProps) { - return await axios.post(`/predict`, data); +export async function sendAll(data: sendAllProps) { + return await axios.post(`/predict`, data); } -export async function checkCode(code:string):Promise>{ - - return await axios.post('/validate/code',{code}) +export async function checkCode( + code: string +): Promise> { + return await axios.post("/validate/code", { code }); } -export async function checkPrompt(template:string):Promise>{ - - return await axios.post('/validate/prompt',{template}) +export async function checkPrompt( + template: string +): Promise> { + return await axios.post("/validate/prompt", { template }); } export async function getExamples(): Promise { - const url = 'https://api.github.com/repos/logspace-ai/langflow_examples/contents/examples'; - const response = await axios.get(url); - - const jsonFiles = response.data.filter((file: any) => { - return file.name.endsWith('.json'); - }); - - const contentsPromises = jsonFiles.map(async (file: any) => { - const contentResponse = await axios.get(file.download_url); - return contentResponse.data; - }); - - const contents = await Promise.all(contentsPromises); - - return contents; - } \ No newline at end of file + const url = + "https://api.github.com/repos/logspace-ai/langflow_examples/contents/examples"; + const response = await axios.get(url); + + const jsonFiles = response.data.filter((file: any) => { + return file.name.endsWith(".json"); + }); + + const contentsPromises = jsonFiles.map(async (file: any) => { + const contentResponse = await axios.get(file.download_url); + return contentResponse.data; + }); + + const contents = await Promise.all(contentsPromises); + + return contents; +} diff --git a/src/frontend/src/pages/FlowPage/index.tsx b/src/frontend/src/pages/FlowPage/index.tsx index 4fc315926..38fe8ecb8 100644 --- a/src/frontend/src/pages/FlowPage/index.tsx +++ b/src/frontend/src/pages/FlowPage/index.tsx @@ -1,15 +1,15 @@ import { useCallback, useContext, useEffect, useRef } from "react"; import ReactFlow, { - Background, - Controls, - addEdge, - useEdgesState, - useNodesState, - useReactFlow, - updateEdge, - EdgeChange, - Connection, - Edge, + Background, + Controls, + addEdge, + useEdgesState, + useNodesState, + useReactFlow, + updateEdge, + EdgeChange, + Connection, + Edge, } from "reactflow"; import { locationContext } from "../../contexts/locationContext"; import ExtraSidebar from "./components/extraSidebarComponent"; @@ -24,193 +24,198 @@ import { APIClassType } from "../../types/api"; import { isValidConnection } from "../../utils"; const nodeTypes = { - genericNode: GenericNode, + genericNode: GenericNode, }; var _ = require("lodash"); -export default function FlowPage({ flow }:{flow:FlowType}) { - let { updateFlow, incrementNodeId} = - useContext(TabsContext); - const { types, reactFlowInstance, setReactFlowInstance } = - useContext(typesContext); - const reactFlowWrapper = useRef(null); +export default function FlowPage({ flow }: { flow: FlowType }) { + let { updateFlow, incrementNodeId } = useContext(TabsContext); + const { types, reactFlowInstance, setReactFlowInstance } = + useContext(typesContext); + const reactFlowWrapper = useRef(null); - const { setExtraComponent, setExtraNavigation } = useContext(locationContext); - const { setErrorData } = useContext(alertContext); - const [nodes, setNodes, onNodesChange] = useNodesState( - flow.data?.nodes ?? [] - ); - const [edges, setEdges, onEdgesChange] = useEdgesState( - flow.data?.edges ?? [] - ); - const { setViewport } = useReactFlow(); - const edgeUpdateSuccessful = useRef(true) + const { setExtraComponent, setExtraNavigation } = useContext(locationContext); + const { setErrorData } = useContext(alertContext); + const [nodes, setNodes, onNodesChange] = useNodesState( + flow.data?.nodes ?? [] + ); + const [edges, setEdges, onEdgesChange] = useEdgesState( + flow.data?.edges ?? [] + ); + const { setViewport } = useReactFlow(); + const edgeUpdateSuccessful = useRef(true); - useEffect(() => { - if (reactFlowInstance && flow) { - flow.data = reactFlowInstance.toObject(); - updateFlow(flow); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [nodes, edges]); - //update flow when tabs change - useEffect(() => { - setNodes(flow?.data?.nodes ?? []); - setEdges(flow?.data?.edges ?? []); - if (reactFlowInstance) { - setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 }); - } - }, [flow, reactFlowInstance, setEdges, setNodes, setViewport]); - //set extra sidebar - useEffect(() => { - setExtraComponent(); - setExtraNavigation({ title: "Components" }); - }, [setExtraComponent, setExtraNavigation]); + useEffect(() => { + if (reactFlowInstance && flow) { + flow.data = reactFlowInstance.toObject(); + updateFlow(flow); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [nodes, edges]); + //update flow when tabs change + useEffect(() => { + setNodes(flow?.data?.nodes ?? []); + setEdges(flow?.data?.edges ?? []); + if (reactFlowInstance) { + setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 }); + } + }, [flow, reactFlowInstance, setEdges, setNodes, setViewport]); + //set extra sidebar + useEffect(() => { + setExtraComponent(); + setExtraNavigation({ title: "Components" }); + }, [setExtraComponent, setExtraNavigation]); - const onEdgesChangeMod = useCallback( - (s:EdgeChange[]) => { - onEdgesChange(s); - setNodes((x) => { - let newX = _.cloneDeep(x); - return newX; - }); - }, - [onEdgesChange, setNodes] - ); + const onEdgesChangeMod = useCallback( + (s: EdgeChange[]) => { + onEdgesChange(s); + setNodes((x) => { + let newX = _.cloneDeep(x); + return newX; + }); + }, + [onEdgesChange, setNodes] + ); - const onConnect = useCallback( - (params:Connection) => { - setEdges((eds) => - addEdge({ ...params, className: "animate-pulse" }, eds) - ); - setNodes((x) => { - let newX = _.cloneDeep(x); - return newX; - }); - }, - [setEdges, setNodes] - ); + const onConnect = useCallback( + (params: Connection) => { + setEdges((eds) => + addEdge({ ...params, className: "animate-pulse" }, eds) + ); + setNodes((x) => { + let newX = _.cloneDeep(x); + return newX; + }); + }, + [setEdges, setNodes] + ); - const onDragOver = useCallback((event:React.DragEvent) => { - event.preventDefault(); - event.dataTransfer.dropEffect = "move"; - }, []); + const onDragOver = useCallback((event: React.DragEvent) => { + event.preventDefault(); + event.dataTransfer.dropEffect = "move"; + }, []); - const onDrop = useCallback( - (event:React.DragEvent) => { - event.preventDefault(); - - // Helper function to generate a unique node ID - function getId() { - return `dndnode_` + incrementNodeId(); - } - - // Get the current bounds of the ReactFlow wrapper element - const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect(); - - // Extract the data from the drag event and parse it as a JSON object - let data:{type:string,node?:APIClassType} = JSON.parse(event.dataTransfer.getData("json")); - - // If data type is not "chatInput" or if there are no "chatInputNode" nodes present in the ReactFlow instance, create a new node - if ( - data.type !== "chatInput" || - (data.type === "chatInput" && - !reactFlowInstance.getNodes().some((n) => n.type === "chatInputNode")) - ) { - // Calculate the position where the node should be created - const position = reactFlowInstance.project({ - x: event.clientX - reactflowBounds.left, - y: event.clientY - reactflowBounds.top, - }); - - // Generate a unique node ID - let newId = getId(); - - // Create a new node object - const newNode:NodeType = { - id: newId, - type: "genericNode", - position, - data: { - ...data, - id: newId, - value: null, - }, - }; - - // Add the new node to the list of nodes in state - setNodes((nds) => nds.concat(newNode)); - } else { - // If a chat input node already exists, set an error message - setErrorData({ - title: "Error creating node", - list: ["There can't be more than one chat input."], - }); - } - }, - // Specify dependencies for useCallback - [incrementNodeId, reactFlowInstance, setErrorData, setNodes] - ); + const onDrop = useCallback( + (event: React.DragEvent) => { + event.preventDefault(); - - const onDelete = (mynodes) => { - setEdges(edges.filter((ns) => !nodes.some((n) => ns.source === n.id || ns.target === n.id))); - } + // Helper function to generate a unique node ID + function getId() { + return `dndnode_` + incrementNodeId(); + } - const onEdgeUpdateStart = useCallback(() => { - edgeUpdateSuccessful.current = false; - }, []); + // Get the current bounds of the ReactFlow wrapper element + const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect(); - - const onEdgeUpdate = useCallback((oldEdge:Edge, newConnection:Connection) => { - if(isValidConnection(newConnection,reactFlowInstance)){ - edgeUpdateSuccessful.current = true; - setEdges((els) => updateEdge(oldEdge, newConnection, els)); - } - }, []); + // Extract the data from the drag event and parse it as a JSON object + let data: { type: string; node?: APIClassType } = JSON.parse( + event.dataTransfer.getData("json") + ); - const onEdgeUpdateEnd = useCallback((_, edge) => { - if (!edgeUpdateSuccessful.current) { - setEdges((eds) => eds.filter((e) => e.id !== edge.id)); - } - - edgeUpdateSuccessful.current = true; - }, []); - - return ( -
- {Object.keys(types).length > 0 ? ( - <> - - updateFlow({ ...flow, data: reactFlowInstance.toObject() }) - } - edges={edges} - onNodesChange={onNodesChange} - onEdgesChange={onEdgesChangeMod} - onConnect={onConnect} - onLoad={setReactFlowInstance} - onInit={setReactFlowInstance} - nodeTypes={nodeTypes} - onEdgeUpdate={onEdgeUpdate} - onEdgeUpdateStart={onEdgeUpdateStart} - onEdgeUpdateEnd={onEdgeUpdateEnd} - connectionLineComponent={ConnectionLineComponent} - onDragOver={onDragOver} - onDrop={onDrop} - onNodesDelete={onDelete} - > - - - - - - - ) : ( - <> - )} -
- ); + // If data type is not "chatInput" or if there are no "chatInputNode" nodes present in the ReactFlow instance, create a new node + if ( + data.type !== "chatInput" || + (data.type === "chatInput" && + !reactFlowInstance.getNodes().some((n) => n.type === "chatInputNode")) + ) { + // Calculate the position where the node should be created + const position = reactFlowInstance.project({ + x: event.clientX - reactflowBounds.left, + y: event.clientY - reactflowBounds.top, + }); + + // Generate a unique node ID + let newId = getId(); + + // Create a new node object + const newNode: NodeType = { + id: newId, + type: "genericNode", + position, + data: { + ...data, + id: newId, + value: null, + }, + }; + + // Add the new node to the list of nodes in state + setNodes((nds) => nds.concat(newNode)); + } else { + // If a chat input node already exists, set an error message + setErrorData({ + title: "Error creating node", + list: ["There can't be more than one chat input."], + }); + } + }, + // Specify dependencies for useCallback + [incrementNodeId, reactFlowInstance, setErrorData, setNodes] + ); + + const onDelete = (mynodes) => { + setEdges( + edges.filter( + (ns) => !nodes.some((n) => ns.source === n.id || ns.target === n.id) + ) + ); + }; + + const onEdgeUpdateStart = useCallback(() => { + edgeUpdateSuccessful.current = false; + }, []); + + const onEdgeUpdate = useCallback( + (oldEdge: Edge, newConnection: Connection) => { + if (isValidConnection(newConnection, reactFlowInstance)) { + edgeUpdateSuccessful.current = true; + setEdges((els) => updateEdge(oldEdge, newConnection, els)); + } + }, + [] + ); + + const onEdgeUpdateEnd = useCallback((_, edge) => { + if (!edgeUpdateSuccessful.current) { + setEdges((eds) => eds.filter((e) => e.id !== edge.id)); + } + + edgeUpdateSuccessful.current = true; + }, []); + + return ( +
+ {Object.keys(types).length > 0 ? ( + <> + + updateFlow({ ...flow, data: reactFlowInstance.toObject() }) + } + edges={edges} + onNodesChange={onNodesChange} + onEdgesChange={onEdgesChangeMod} + onConnect={onConnect} + onLoad={setReactFlowInstance} + onInit={setReactFlowInstance} + nodeTypes={nodeTypes} + onEdgeUpdate={onEdgeUpdate} + onEdgeUpdateStart={onEdgeUpdateStart} + onEdgeUpdateEnd={onEdgeUpdateEnd} + connectionLineComponent={ConnectionLineComponent} + onDragOver={onDragOver} + onDrop={onDrop} + onNodesDelete={onDelete} + > + + + + + + ) : ( + <> + )} +
+ ); } diff --git a/src/frontend/src/reportWebVitals.ts b/src/frontend/src/reportWebVitals.ts index 49a2a16e0..5fa3583b7 100644 --- a/src/frontend/src/reportWebVitals.ts +++ b/src/frontend/src/reportWebVitals.ts @@ -1,8 +1,8 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals"; const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/src/frontend/src/svg.d.ts b/src/frontend/src/svg.d.ts index a6e109e02..1a3dd3c2a 100644 --- a/src/frontend/src/svg.d.ts +++ b/src/frontend/src/svg.d.ts @@ -1,5 +1,4 @@ -declare module '*.svg' { - const content: any; - export default content; - } - \ No newline at end of file +declare module "*.svg" { + const content: any; + export default content; +} diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 4a2afcd18..8d26c4e15 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -1,20 +1,40 @@ -import { Node,Edge,Viewport } from "reactflow" +import { Node, Edge, Viewport } from "reactflow"; //kind and class are just representative names to represent the actual structure of the object received by the API -export type APIObjectType = {kind:APIKindType,[key:string]:APIKindType} -export type APIKindType= {class:APIClassType,[key:string]:APIClassType} -export type APITemplateType = {variable:TemplateVariableType,[key:string]:TemplateVariableType} -export type APIClassType ={base_classes:Array,description:string,template:APITemplateType,[key:string]:Array|string|APITemplateType} -export type TemplateVariableType = {type:string,required:boolean,placeholder?:string,list:boolean,show:boolean,multiline?:boolean,value?:any,[key:string]:any} -export type sendAllProps={ - nodes: Node[]; - edges: Edge[]; - name:string, - description:string; - viewport: Viewport; - message:string; - - chatHistory:{message:string,isSend:boolean}[], +export type APIObjectType = { kind: APIKindType; [key: string]: APIKindType }; +export type APIKindType = { class: APIClassType; [key: string]: APIClassType }; +export type APITemplateType = { + variable: TemplateVariableType; + [key: string]: TemplateVariableType; }; -export type errorsTypeAPI={function:{errors:Array},imports:{errors:Array}} -export type PromptTypeAPI = {input_variables:Array} \ No newline at end of file +export type APIClassType = { + base_classes: Array; + description: string; + template: APITemplateType; + [key: string]: Array | string | APITemplateType; +}; +export type TemplateVariableType = { + type: string; + required: boolean; + placeholder?: string; + list: boolean; + show: boolean; + multiline?: boolean; + value?: any; + [key: string]: any; +}; +export type sendAllProps = { + nodes: Node[]; + edges: Edge[]; + name: string; + description: string; + viewport: Viewport; + message: string; + + chatHistory: { message: string; isSend: boolean }[]; +}; +export type errorsTypeAPI = { + function: { errors: Array }; + imports: { errors: Array }; +}; +export type PromptTypeAPI = { input_variables: Array }; diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index d7448083e..e8c682724 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,81 +1,85 @@ import { ForwardRefExoticComponent, ReactElement, ReactNode } from "react"; import { NodeDataType } from "../flow/index"; export type InputComponentType = { - value: string; - disabled?: boolean; - onChange: (value: string) => void; - password: boolean; + value: string; + disabled?: boolean; + onChange: (value: string) => void; + password: boolean; }; export type ToggleComponentType = { - enabled: boolean; - setEnabled: (state: boolean) => void; - disabled: boolean; + enabled: boolean; + setEnabled: (state: boolean) => void; + disabled: boolean; }; export type DropDownComponentType = { - value: string; - options: string[]; - onSelect: (value: string) => void; + value: string; + options: string[]; + onSelect: (value: string) => void; }; export type ParameterComponentType = { - data: NodeDataType; - title: string; - id: string; - color: string; - left: boolean; - type: string; - required?: boolean; - name?: string; - tooltipTitle: string; + data: NodeDataType; + title: string; + id: string; + color: string; + left: boolean; + type: string; + required?: boolean; + name?: string; + tooltipTitle: string; }; export type InputListComponentType = { - value: string[]; - onChange: (value: string[]) => void; - disabled: boolean; + value: string[]; + onChange: (value: string[]) => void; + disabled: boolean; }; export type TextAreaComponentType = { - disabled: boolean; - onChange: (value: string[] | string) => void; - value: string; + disabled: boolean; + onChange: (value: string[] | string) => void; + value: string; }; export type FileComponentType = { - disabled: boolean; - onChange: (value: string[] | string) => void; - value: string; - suffixes:Array; - fileTypes:Array; - onFileChange:(value: string) => void; + disabled: boolean; + onChange: (value: string[] | string) => void; + value: string; + suffixes: Array; + fileTypes: Array; + onFileChange: (value: string) => void; }; export type DisclosureComponentType = { - children: ReactNode; - button: { - title: string; - Icon: ForwardRefExoticComponent>; - buttons?: { - Icon: ReactElement; - title: string; - onClick: (event?: React.MouseEvent) => void; - }[]; - }; + children: ReactNode; + button: { + title: string; + Icon: ForwardRefExoticComponent>; + buttons?: { + Icon: ReactElement; + title: string; + onClick: (event?: React.MouseEvent) => void; + }[]; + }; }; export type FloatComponentType = { - value: string; - disabled?: boolean; - onChange: (value: string) => void; + value: string; + disabled?: boolean; + onChange: (value: string) => void; }; -export type TooltipComponentType={children:ReactElement,title:string,placement?: - | 'bottom-end' - | 'bottom-start' - | 'bottom' - | 'left-end' - | 'left-start' - | 'left' - | 'right-end' - | 'right-start' - | 'right' - | 'top-end' - | 'top-start' - | 'top';} \ No newline at end of file +export type TooltipComponentType = { + children: ReactElement; + title: string; + placement?: + | "bottom-end" + | "bottom-start" + | "bottom" + | "left-end" + | "left-start" + | "left" + | "right-end" + | "right-start" + | "right" + | "top-end" + | "top-start" + | "top"; +}; diff --git a/src/frontend/src/types/entities/index.ts b/src/frontend/src/types/entities/index.ts index c0d591cfc..3c0877579 100644 --- a/src/frontend/src/types/entities/index.ts +++ b/src/frontend/src/types/entities/index.ts @@ -1,3 +1,8 @@ import { HomeIcon } from "@heroicons/react/24/outline"; -export type sidebarNavigationItemType = { name: string, href: string, icon: React.ForwardRefExoticComponent>, current: boolean } +export type sidebarNavigationItemType = { + name: string; + href: string; + icon: React.ForwardRefExoticComponent>; + current: boolean; +}; diff --git a/src/frontend/src/types/flow/index.ts b/src/frontend/src/types/flow/index.ts index 26354c55c..6c118aa49 100644 --- a/src/frontend/src/types/flow/index.ts +++ b/src/frontend/src/types/flow/index.ts @@ -1,12 +1,22 @@ -import { ChatMessageType } from './../chat/index'; -import { APIClassType } from '../api/index'; +import { ChatMessageType } from "./../chat/index"; +import { APIClassType } from "../api/index"; import { ReactFlowJsonObject, XYPosition } from "reactflow"; export type FlowType = { - name: string; - id: string; - data: ReactFlowJsonObject; - description:string; + name: string; + id: string; + data: ReactFlowJsonObject; + description: string; +}; +export type NodeType = { + id: string; + type?: string; + position: XYPosition; + data: NodeDataType; +}; +export type NodeDataType = { + type: string; + node?: APIClassType; + id: string; + value: any; }; -export type NodeType = {id:string,type:string,position:XYPosition,data:NodeDataType} -export type NodeDataType = {type:string,node?:APIClassType,id:string,value:any} \ No newline at end of file diff --git a/src/frontend/src/types/tabs/index.ts b/src/frontend/src/types/tabs/index.ts index 1b675e0c5..3fffbcd8a 100644 --- a/src/frontend/src/types/tabs/index.ts +++ b/src/frontend/src/types/tabs/index.ts @@ -1,15 +1,15 @@ import { FlowType } from "../flow"; export type TabsContextType = { - save:()=>void; - tabIndex: number; - setTabIndex: (index: number) => void; - flows: Array; - removeFlow: (id: string) => void; - addFlow: (flowData?: FlowType) => void; - updateFlow: (newFlow: FlowType) => void; - incrementNodeId: () => number; - downloadFlow: (flow:FlowType) => void; - uploadFlow: () => void; - hardReset:()=>void; -}; \ No newline at end of file + save: () => void; + tabIndex: number; + setTabIndex: (index: number) => void; + flows: Array; + removeFlow: (id: string) => void; + addFlow: (flowData?: FlowType) => void; + updateFlow: (newFlow: FlowType) => void; + incrementNodeId: () => number; + downloadFlow: (flow: FlowType) => void; + uploadFlow: () => void; + hardReset: () => void; +}; diff --git a/src/frontend/src/types/typesContext/index.ts b/src/frontend/src/types/typesContext/index.ts index e943dafe3..f3a8612b5 100644 --- a/src/frontend/src/types/typesContext/index.ts +++ b/src/frontend/src/types/typesContext/index.ts @@ -1,11 +1,11 @@ import { ReactFlowInstance } from "reactflow"; -const types:{[char: string]: string}={} +const types: { [char: string]: string } = {}; export type typesContextType = { - reactFlowInstance: ReactFlowInstance|null; - setReactFlowInstance: any; - deleteNode: (idx: string) => void; - types: typeof types; - setTypes: (newState: {}) => void; -}; \ No newline at end of file + reactFlowInstance: ReactFlowInstance | null; + setReactFlowInstance: any; + deleteNode: (idx: string) => void; + types: typeof types; + setTypes: (newState: {}) => void; +}; diff --git a/src/frontend/src/utils.ts b/src/frontend/src/utils.ts index 608035ff8..c7457a70b 100644 --- a/src/frontend/src/utils.ts +++ b/src/frontend/src/utils.ts @@ -14,13 +14,13 @@ import { FingerPrintIcon, ScissorsIcon, CircleStackIcon, - Squares2X2Icon + Squares2X2Icon, } from "@heroicons/react/24/outline"; import { Connection, Edge, Node, ReactFlowInstance } from "reactflow"; import { FlowType } from "./types/flow"; -var _ = require('lodash') +var _ = require("lodash"); -export function classNames(...classes:Array) { +export function classNames(...classes: Array) { return classes.filter(Boolean).join(" "); } @@ -70,7 +70,7 @@ export const borderLColors = { gray: "border-l-gray-500", }; -export const nodeColors: {[char: string]: string} = { +export const nodeColors: { [char: string]: string } = { prompts: "#4367BF", llms: "#6344BE", chains: "#FE7500", @@ -79,18 +79,18 @@ export const nodeColors: {[char: string]: string} = { memories: "#F5B85A", advanced: "#000000", chat: "#198BF6", - thought:"#272541", - embeddings:"#42BAA7", - documentloaders:"#7AAE42", + thought: "#272541", + embeddings: "#42BAA7", + documentloaders: "#7AAE42", vectorstores: "#AA8742", textsplitters: "#B47CB5", - toolkits:"#DB2C2C", - wrappers:"#E6277A", - utilities:"#31A3CC", - unknown:"#9CA3AF" + toolkits: "#DB2C2C", + wrappers: "#E6277A", + utilities: "#31A3CC", + unknown: "#9CA3AF", }; -export const nodeNames:{[char: string]: string} = { +export const nodeNames: { [char: string]: string } = { prompts: "Prompts", llms: "LLMs", chains: "Chains", @@ -102,14 +102,18 @@ export const nodeNames:{[char: string]: string} = { embeddings: "Embeddings", documentloaders: "Document Loaders", vectorstores: "Vector Stores", - toolkits:"Toolkits", - wrappers:"Wrappers", + toolkits: "Toolkits", + wrappers: "Wrappers", textsplitters: "Text Splitters", - utilities:"Utilities", - unknown:"Unknown" + utilities: "Utilities", + unknown: "Unknown", }; -export const nodeIcons:{[char: string]: React.ForwardRefExoticComponent>} = { +export const nodeIcons: { + [char: string]: React.ForwardRefExoticComponent< + React.SVGProps + >; +} = { agents: RocketLaunchIcon, chains: LinkIcon, memories: CpuChipIcon, @@ -118,14 +122,14 @@ export const nodeIcons:{[char: string]: React.ForwardRefExoticComponent { - if (index === 0) { - return word[0].toUpperCase() + word.slice(1).toLowerCase(); - } - return word.toLowerCase(); - }) - .join("_"); + .split(" ") + .map((word, index) => { + if (index === 0) { + return word[0].toUpperCase() + word.slice(1).toLowerCase(); + } + return word.toLowerCase(); + }) + .join("_"); } -export function roundNumber(x:number, decimals:number) { +export function roundNumber(x: number, decimals: number) { return Math.round(x * Math.pow(10, decimals)) / Math.pow(10, decimals); } @@ -345,12 +353,15 @@ export function getConnectedNodes(edge: Edge, nodes: Array): Array { } export function isValidConnection( - { source, target, sourceHandle, targetHandle }:Connection, - reactFlowInstance:ReactFlowInstance + { source, target, sourceHandle, targetHandle }: Connection, + reactFlowInstance: ReactFlowInstance ) { if ( - sourceHandle.split('|')[0] === targetHandle.split("|")[0] || - sourceHandle.split('|').slice(2).some((t) => t === targetHandle.split("|")[0]) || + sourceHandle.split("|")[0] === targetHandle.split("|")[0] || + sourceHandle + .split("|") + .slice(2) + .some((t) => t === targetHandle.split("|")[0]) || targetHandle.split("|")[0] === "str" ) { let targetNode = reactFlowInstance.getNode(target).data.node; @@ -375,16 +386,15 @@ export function isValidConnection( return false; } -export function removeApiKeys(flow:FlowType):FlowType{ - let cleanFLow = _.cloneDeep(flow) - cleanFLow.data.nodes.forEach(node=>{ - for(const key in node.data.node.template) - { - if(key.includes('api')){ - console.log(node.data.node.template[key]) - node.data.node.template[key].value = '' +export function removeApiKeys(flow: FlowType): FlowType { + let cleanFLow = _.cloneDeep(flow); + cleanFLow.data.nodes.forEach((node) => { + for (const key in node.data.node.template) { + if (key.includes("api")) { + console.log(node.data.node.template[key]); + node.data.node.template[key].value = ""; } } - }) - return cleanFLow -} \ No newline at end of file + }); + return cleanFLow; +}