Merge branch 'cz/mergeAll' into two_edges

This commit is contained in:
ogabrielluiz 2024-06-10 15:57:46 -03:00
commit 921250cbe1
63 changed files with 711 additions and 738 deletions

View file

@ -684,7 +684,6 @@
"max": 1, "max": 1,
"step": 0.1 "step": 0.1
}, },
<<<<<<< HEAD
"data": { "data": {
"type": "Prompt", "type": "Prompt",
"node": { "node": {
@ -823,8 +822,7 @@
"x": 2969.0261961391298, "x": 2969.0261961391298,
"y": 442.1613649809069 "y": 442.1613649809069
}, },
"dragging": false "dragging": false,
=======
"load_from_db": false, "load_from_db": false,
"title_case": false "title_case": false
}, },
@ -907,7 +905,6 @@
] ]
}, },
"_type": "CustomComponent" "_type": "CustomComponent"
>>>>>>> origin/dev
}, },
"description": "Generate embeddings using OpenAI models.", "description": "Generate embeddings using OpenAI models.",
"base_classes": [ "base_classes": [

View file

@ -219,7 +219,7 @@ async def build_and_cache_graph_from_db(flow_id: str, session: Session, chat_ser
if vertex is None: if vertex is None:
raise ValueError(f"Vertex {vertex_id} not found") raise ValueError(f"Vertex {vertex_id} not found")
if not vertex._raw_params.get("session_id"): if not vertex._raw_params.get("session_id"):
vertex.update_raw_params({"session_id": flow_id}) vertex.update_raw_params({"session_id": flow_id}, overwrite=True)
await chat_service.set_cache(flow_id, graph) await chat_service.set_cache(flow_id, graph)
return graph return graph

View file

@ -0,0 +1,24 @@
from langflow.schema import Record
def chroma_collection_to_records(collection_dict: dict):
"""
Converts a collection of chroma vectors into a list of records.
Args:
collection_dict (dict): A dictionary containing the collection of chroma vectors.
Returns:
list: A list of records, where each record represents a document in the collection.
"""
records = []
for i, doc in enumerate(collection_dict["documents"]):
record_dict = {
"id": collection_dict["ids"][i],
"text": doc,
}
if "metadatas" in collection_dict:
for key, value in collection_dict["metadatas"][i].items():
record_dict[key] = value
records.append(Record(**record_dict))
return records

View file

@ -15,4 +15,5 @@ class RecordsOutput(Component):
] ]
def record_response(self) -> Record: def record_response(self) -> Record:
self.status = self.input_value
return self.input_value return self.input_value

View file

@ -0,0 +1,68 @@
# from langflow.field_typing import Data
from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_core.vectorstores import VectorStore
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel, Text
from langflow.schema import Record
from langflow.schema.message import Message
class SelfQueryRetrieverComponent(CustomComponent):
display_name: str = "Self Query Retriever"
description: str = "Retriever that uses a vector store and an LLM to generate the vector store queries."
icon = "LangChain"
def build_config(self):
return {
"query": {
"display_name": "Query",
"input_types": ["Message", "Text"],
"info": "Query to be passed as input.",
},
"vectorstore": {
"display_name": "Vector Store",
"info": "Vector Store to be passed as input.",
},
"attribute_infos": {
"display_name": "Metadata Field Info",
"info": "Metadata Field Info to be passed as input.",
},
"document_content_description": {
"display_name": "Document Content Description",
"info": "Document Content Description to be passed as input.",
},
"llm": {
"display_name": "LLM",
"info": "LLM to be passed as input.",
},
}
def build(
self,
query: Message,
vectorstore: VectorStore,
attribute_infos: list[Record],
document_content_description: Text,
llm: BaseLanguageModel,
) -> Record:
metadata_field_infos = [AttributeInfo(**record.data) for record in attribute_infos]
self_query_retriever = SelfQueryRetriever.from_llm(
llm=llm,
vectorstore=vectorstore,
document_contents=document_content_description,
metadata_field_info=metadata_field_infos,
enable_limit=True,
)
if isinstance(query, Message):
input_text = query.text
elif isinstance(query, str):
input_text = query
else:
raise ValueError(f"Query type {type(query)} not supported.")
documents = self_query_retriever.invoke(input=input_text)
records = [Record.from_document(document) for document in documents]
self.status = records
return records

View file

@ -1,3 +1,4 @@
from copy import deepcopy
from typing import List, Optional, Union from typing import List, Optional, Union
import chromadb import chromadb
@ -7,6 +8,7 @@ from langchain_core.embeddings import Embeddings
from langchain_core.retrievers import BaseRetriever from langchain_core.retrievers import BaseRetriever
from langchain_core.vectorstores import VectorStore from langchain_core.vectorstores import VectorStore
from langflow.base.vectorstores.utils import chroma_collection_to_records
from langflow.custom import CustomComponent from langflow.custom import CustomComponent
from langflow.schema import Record from langflow.schema import Record
@ -48,6 +50,11 @@ class ChromaComponent(CustomComponent):
"display_name": "Server SSL Enabled", "display_name": "Server SSL Enabled",
"advanced": True, "advanced": True,
}, },
"allow_duplicates": {
"display_name": "Allow Duplicates",
"advanced": True,
"info": "If false, will not add documents that are already in the Vector Store.",
},
} }
def build( def build(
@ -61,6 +68,7 @@ class ChromaComponent(CustomComponent):
chroma_server_host: Optional[str] = None, chroma_server_host: Optional[str] = None,
chroma_server_http_port: Optional[int] = None, chroma_server_http_port: Optional[int] = None,
chroma_server_grpc_port: Optional[int] = None, chroma_server_grpc_port: Optional[int] = None,
allow_duplicates: bool = False,
) -> Union[VectorStore, BaseRetriever]: ) -> Union[VectorStore, BaseRetriever]:
""" """
Builds the Vector Store or BaseRetriever object. Builds the Vector Store or BaseRetriever object.
@ -75,6 +83,7 @@ class ChromaComponent(CustomComponent):
- chroma_server_host (Optional[str]): The host for the Chroma server. - chroma_server_host (Optional[str]): The host for the Chroma server.
- chroma_server_http_port (Optional[int]): The HTTP port for the Chroma server. - chroma_server_http_port (Optional[int]): The HTTP port for the Chroma server.
- chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server. - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.
- allow_duplicates (bool): Whether to allow duplicates in the Vector Store.
Returns: Returns:
- Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object. - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.
@ -93,32 +102,34 @@ class ChromaComponent(CustomComponent):
) )
client = chromadb.HttpClient(settings=chroma_settings) client = chromadb.HttpClient(settings=chroma_settings)
# If documents, then we need to create a Chroma instance using .from_documents
# Check index_directory and expand it if it is a relative path # Check index_directory and expand it if it is a relative path
if index_directory is not None: if index_directory is not None:
index_directory = self.resolve_path(index_directory) index_directory = self.resolve_path(index_directory)
documents = []
for _input in inputs or []:
if isinstance(_input, Record):
documents.append(_input.to_lc_document())
else:
documents.append(_input)
if documents is not None and embedding is not None:
if len(documents) == 0:
raise ValueError("If documents are provided, there must be at least one document.")
chroma = Chroma.from_documents(
documents=documents, # type: ignore
persist_directory=index_directory,
collection_name=collection_name,
embedding=embedding,
client=client,
)
else:
chroma = Chroma( chroma = Chroma(
persist_directory=index_directory, persist_directory=index_directory,
client=client, client=client,
embedding_function=embedding, embedding_function=embedding,
collection_name=collection_name,
) )
if allow_duplicates:
stored_records = []
else:
stored_records = chroma_collection_to_records(chroma.get())
_stored_documents_without_id = []
for record in deepcopy(stored_records):
del record.id
_stored_documents_without_id.append(record)
documents = []
for _input in inputs or []:
if isinstance(_input, Record):
if _input not in _stored_documents_without_id:
documents.append(_input.to_lc_document())
else:
raise ValueError("Inputs must be a Record objects.")
if documents and embedding is not None:
chroma.add_documents(documents)
self.status = stored_records
return chroma return chroma

View file

@ -123,8 +123,11 @@ class CustomComponent(BaseComponent):
@staticmethod @staticmethod
def resolve_path(path: str) -> str: def resolve_path(path: str) -> str:
"""Resolves the path to an absolute path.""" """Resolves the path to an absolute path."""
if not path:
return path
path_object = Path(path) path_object = Path(path)
if path_object.parts[0] == "~":
if path_object.parts and path_object.parts[0] == "~":
path_object = path_object.expanduser() path_object = path_object.expanduser()
elif path_object.is_relative_to("."): elif path_object.is_relative_to("."):
path_object = path_object.resolve() path_object = path_object.resolve()

View file

@ -25,6 +25,7 @@ class Prompt(Record):
prompt_template = PromptTemplate.from_template(self.template) prompt_template = PromptTemplate.from_template(self.template)
variables_with_str_values = dict_values_to_string(self.variables) variables_with_str_values = dict_values_to_string(self.variables)
formatted_prompt = prompt_template.format(**variables_with_str_values) formatted_prompt = prompt_template.format(**variables_with_str_values)
self.text = formatted_prompt
return formatted_prompt return formatted_prompt
@classmethod @classmethod

View file

@ -1,12 +1,12 @@
import copy import copy
import json import json
from typing import cast, Optional from typing import Optional, cast
from langchain_core.documents import Document from langchain_core.documents import Document
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
from langchain_core.prompt_values import ImagePromptValue
from langchain_core.prompts.image import ImagePromptTemplate from langchain_core.prompts.image import ImagePromptTemplate
from pydantic import BaseModel, model_serializer, model_validator from pydantic import BaseModel, model_serializer, model_validator
from langchain_core.prompt_values import ImagePromptValue
class Record(BaseModel): class Record(BaseModel):
@ -200,3 +200,6 @@ class Record(BaseModel):
def __contains__(self, key): def __contains__(self, key):
return key in self.data return key in self.data
def __eq__(self, other):
return isinstance(other, Record) and self.data == other.data

View file

@ -82,7 +82,7 @@
"start": "vite", "start": "vite",
"build": "vite build", "build": "vite build",
"serve": "vite preview", "serve": "vite preview",
"format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore", "format": "npx prettier --write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite" "type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
}, },
"simple-git-hooks": { "simple-git-hooks": {

View file

@ -28,7 +28,6 @@ export default function SwitchOutputView(nodeId): JSX.Element {
if (resultMessage.raw) { if (resultMessage.raw) {
resultMessage = resultMessage.raw; resultMessage = resultMessage.raw;
} }
console.log("resultType", results);
return ( return (
<> <>
<Case condition={!resultType || resultType === "unknown"}> <Case condition={!resultType || resultType === "unknown"}>

View file

@ -43,6 +43,7 @@ import useHandleNodeClass from "../../../hooks/use-handle-node-class";
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons"; import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
import HandleTooltips from "../HandleTooltipComponent"; import HandleTooltips from "../HandleTooltipComponent";
import OutputComponent from "../OutputComponent"; import OutputComponent from "../OutputComponent";
import OutputModal from "../outputModal";
import { TEXT_FIELD_TYPES } from "./constants"; import { TEXT_FIELD_TYPES } from "./constants";
export default function ParameterComponent({ export default function ParameterComponent({
@ -64,6 +65,7 @@ export default function ParameterComponent({
outputProxy, outputProxy,
}: ParameterComponentType): JSX.Element { }: ParameterComponentType): JSX.Element {
const infoHtml = useRef<HTMLDivElement & ReactNode>(null); const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
const nodes = useFlowStore((state) => state.nodes); const nodes = useFlowStore((state) => state.nodes);
const edges = useFlowStore((state) => state.edges); const edges = useFlowStore((state) => state.edges);
const setNode = useFlowStore((state) => state.setNode); const setNode = useFlowStore((state) => state.setNode);
@ -73,6 +75,17 @@ export default function ParameterComponent({
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge); const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const [openOutputModal, setOpenOutputModal] = useState(false);
const flowPool = useFlowStore((state) => state.flowPool);
const displayOutputPreview = !!flowPool[data.id];
const unknownOutput = !!(
flowPool[data.id] &&
flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.type ===
"unknown"
);
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue( const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue(
data, data,
name, name,
@ -80,7 +93,7 @@ export default function ParameterComponent({
handleUpdateValues, handleUpdateValues,
debouncedHandleUpdateValues, debouncedHandleUpdateValues,
setNode, setNode,
setIsLoading, setIsLoading
); );
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
@ -88,7 +101,7 @@ export default function ParameterComponent({
name, name,
takeSnapshot, takeSnapshot,
setNode, setNode,
updateNodeInternals, updateNodeInternals
); );
const { handleRefreshButtonPress: handleRefreshButtonPressHook } = const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
@ -97,7 +110,7 @@ export default function ParameterComponent({
let disabled = let disabled =
edges.some( edges.some(
(edge) => (edge) =>
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
) ?? false; ) ?? false;
const handleRefreshButtonPress = async (name, data) => { const handleRefreshButtonPress = async (name, data) => {
@ -108,7 +121,7 @@ export default function ParameterComponent({
const handleOnNewValue = async ( const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[], newValue: string | string[] | boolean | Object[],
skipSnapshot: boolean | undefined = false, skipSnapshot: boolean | undefined = false
): Promise<void> => { ): Promise<void> => {
handleOnNewValueHook(newValue, skipSnapshot); handleOnNewValueHook(newValue, skipSnapshot);
}; };
@ -195,14 +208,14 @@ export default function ParameterComponent({
className={classNames( className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background", "h-3 w-3 rounded-full border-2 bg-background",
!showNode ? "mt-0" : "", !showNode ? "mt-0" : ""
)} )}
style={{ style={{
borderColor: color ?? nodeColors.unknown, borderColor: color ?? nodeColors.unknown,
}} }}
onClick={() => { onClick={() => {
setFilterEdge( setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!), groupByFamily(myData, tooltipTitle!, left, nodes!)
); );
}} }}
></Handle> ></Handle>
@ -238,7 +251,40 @@ export default function ParameterComponent({
{renderTitle()} {renderTitle()}
</ShadTooltip> </ShadTooltip>
) : ( ) : (
renderTitle() <div className="flex gap-2">
<span className={!left && data.node?.frozen ? " text-ice" : ""}>
{renderTitle()}
</span>
{!left && (
<ShadTooltip
content={
displayOutputPreview
? unknownOutput
? "Output can't be displayed"
: "Inspect Output"
: "Please build the component first"
}
>
<Button
variant="none"
size="none"
disabled={!displayOutputPreview || unknownOutput}
onClick={() => setOpenOutputModal(true)}
data-testid={`output-inspection-${title.toLowerCase()}`}
>
<IconComponent
className={classNames(
"h-5 w-5 rounded-md",
displayOutputPreview && !unknownOutput
? " hover:bg-secondary-foreground/5 hover:text-medium-indigo"
: " cursor-not-allowed text-muted-foreground"
)}
name={"ScanEye"}
/>
</Button>
</ShadTooltip>
)}
</div>
)} )}
<span className={(required ? "ml-2 " : "") + "text-status-red"}> <span className={(required ? "ml-2 " : "") + "text-status-red"}>
{required ? "*" : ""} {required ? "*" : ""}
@ -287,12 +333,12 @@ export default function ParameterComponent({
} }
className={classNames( className={classNames(
left ? "-ml-0.5" : "-mr-0.5", left ? "-ml-0.5" : "-mr-0.5",
"h-3 w-3 rounded-full border-2 bg-background", "h-3 w-3 rounded-full border-2 bg-background"
)} )}
style={{ borderColor: color ?? nodeColors.unknown }} style={{ borderColor: color ?? nodeColors.unknown }}
onClick={() => { onClick={() => {
setFilterEdge( setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!), groupByFamily(myData, tooltipTitle!, left, nodes!)
); );
}} }}
/> />
@ -387,7 +433,7 @@ export default function ParameterComponent({
}); });
}} }}
name={name} name={name}
data={data.node?.template[name]} data={data.node?.template[name]!}
/> />
</div> </div>
{data.node?.template[name]?.refresh_button && ( {data.node?.template[name]?.refresh_button && (
@ -574,6 +620,13 @@ export default function ParameterComponent({
/> />
</div> </div>
</Case> </Case>
{openOutputModal && (
<OutputModal
open={openOutputModal}
nodeId={data.id}
setOpen={setOpenOutputModal}
/>
)}
</> </>
</div> </div>
); );

View file

@ -1,47 +1,52 @@
import emojiRegex from "emoji-regex"; import emojiRegex from "emoji-regex";
import { cloneDeep } from "lodash"; import { useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import InputComponent from "../../components/inputComponent"; import InputComponent from "../../components/inputComponent";
import ShadTooltip from "../../components/shadTooltipComponent"; import ShadTooltip from "../../components/shadTooltipComponent";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import Checkmark from "../../components/ui/checkmark";
import Loading from "../../components/ui/loading";
import { Textarea } from "../../components/ui/textarea"; import { Textarea } from "../../components/ui/textarea";
import Xmark from "../../components/ui/xmark";
import { import {
RUN_TIMESTAMP_PREFIX, RUN_TIMESTAMP_PREFIX,
STATUS_BUILD, STATUS_BUILD,
STATUS_BUILDING, STATUS_BUILDING,
TOOLTIP_OUTDATED_NODE,
} from "../../constants/constants"; } from "../../constants/constants";
import { BuildStatus } from "../../constants/enums"; import { BuildStatus } from "../../constants/enums";
import { postCustomComponent } from "../../controllers/API";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import { useDarkStore } from "../../stores/darkStore"; import { useDarkStore } from "../../stores/darkStore";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../stores/shortcuts";
import { useTypesStore } from "../../stores/typesStore"; import { useTypesStore } from "../../stores/typesStore";
import { APIClassType } from "../../types/api"; import { VertexBuildTypeAPI } from "../../types/api";
import { validationStatusType } from "../../types/components";
import { NodeDataType } from "../../types/flow"; import { NodeDataType } from "../../types/flow";
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils"; import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
import { classNames, cn } from "../../utils/utils"; import { classNames, cn } from "../../utils/utils";
import { countHandlesFn } from "../helpers/count-handles";
import { getSpecificClassFromBuildStatus } from "../helpers/get-class-from-build-status";
import useCheckCodeValidity from "../hooks/use-check-code-validity";
import useIconNodeRender from "../hooks/use-icon-render";
import useIconStatus from "../hooks/use-icons-status";
import useUpdateNodeCode from "../hooks/use-update-node-code";
import useUpdateValidationStatus from "../hooks/use-update-validation-status";
import useValidationStatusString from "../hooks/use-validation-status-string";
import getFieldTitle from "../utils/get-field-title"; import getFieldTitle from "../utils/get-field-title";
import sortFields from "../utils/sort-fields"; import sortFields from "../utils/sort-fields";
import ParameterComponent from "./components/parameterComponent"; import ParameterComponent from "./components/parameterComponent";
export default function GenericNode({ export default function GenericNode({
data, data,
xPos,
yPos,
selected, selected,
}: { }: {
data: NodeDataType; data: NodeDataType;
selected: boolean; selected: boolean;
xPos: number; xPos?: number;
yPos: number; yPos?: number;
}): JSX.Element { }): JSX.Element {
const types = useTypesStore((state) => state.types); const types = useTypesStore((state) => state.types);
const templates = useTypesStore((state) => state.templates); const templates = useTypesStore((state) => state.templates);
@ -51,192 +56,47 @@ export default function GenericNode({
const setNode = useFlowStore((state) => state.setNode); const setNode = useFlowStore((state) => state.setNode);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; const isDark = useDarkStore((state) => state.dark);
const buildStatus = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.status
);
const lastRunTime = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.timestamp
);
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const [inputName, setInputName] = useState(false); const [inputName, setInputName] = useState(false);
const [nodeName, setNodeName] = useState(data.node!.display_name); const [nodeName, setNodeName] = useState(data.node!.display_name);
const [inputDescription, setInputDescription] = useState(false); const [inputDescription, setInputDescription] = useState(false);
const [nodeDescription, setNodeDescription] = useState( const [nodeDescription, setNodeDescription] = useState(
data.node?.description!, data.node?.description!
); );
const [isOutdated, setIsOutdated] = useState(false); const [isOutdated, setIsOutdated] = useState(false);
const buildStatus = useFlowStore( const buildStatus = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.status, (state) => state.flowBuildStatus[data.id]?.status
); );
const lastRunTime = useFlowStore( const lastRunTime = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.timestamp, (state) => state.flowBuildStatus[data.id]?.timestamp
); );
const [validationStatus, setValidationStatus] = const [validationStatus, setValidationStatus] =
useState<validationStatusType | null>(null); useState<VertexBuildTypeAPI | null>(null);
const [handles, setHandles] = useState<number>(0); const [handles, setHandles] = useState<number>(0);
const [validationString, setValidationString] = useState<string>(""); const [validationString, setValidationString] = useState<string>("");
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); const iconStatus = useIconStatus(buildStatus, validationStatus);
const [showNode, setShowNode] = useState(data.showNode ?? true);
useEffect(() => {
// This one should run only once
// first check if data.type in NATIVE_CATEGORIES
// if not return
if (!data.node?.template?.code?.value) return;
const thisNodeTemplate = templates[data.type]?.template;
// if the template does not have a code key
// return
if (!thisNodeTemplate?.code) return;
const currentCode = thisNodeTemplate.code?.value;
const thisNodesCode = data.node!.template?.code?.value;
const componentsToIgnore = ["Custom Component"];
if (
currentCode !== thisNodesCode &&
!componentsToIgnore.includes(data.node!.display_name)
) {
setIsOutdated(true);
} else {
setIsOutdated(false);
}
// template.code can be undefined
}, [data.node?.template?.code?.value]);
const updateNodeCode = useCallback(
(newNodeClass: APIClassType, code: string, name: string) => {
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
node: newNodeClass,
description: newNodeClass.description ?? data.node!.description,
display_name: newNodeClass.display_name ?? data.node!.display_name,
};
newNode.data.node.template[name].value = code;
setIsOutdated(false);
return newNode;
});
updateNodeInternals(data.id);
},
[data.id, data.node, setNode, setIsOutdated],
);
if (!data.node!.template) {
setErrorData({
title: `Error in component ${data.node!.display_name}`,
list: [
`The component ${data.node!.display_name} has no template.`,
`Please contact the developer of the component to fix this issue.`,
],
});
takeSnapshot();
deleteNode(data.id);
}
function countHandles(): void {
let count = Object.keys(data.node!.template)
.filter((templateField) => templateField.charAt(0) !== "_")
.map((templateCamp) => {
const { template } = data.node!;
if (template[templateCamp].input_types) return true;
if (!template[templateCamp].show) return false;
switch (template[templateCamp].type) {
case "str":
case "bool":
case "float":
case "code":
case "prompt":
case "file":
case "int":
return false;
default:
return true;
}
})
.reduce((total, value) => total + (value ? 1 : 0), 0);
setHandles(count);
}
useEffect(() => {
countHandles();
}, [data, data.node]);
useEffect(() => {
if (!selected) {
setInputName(false);
setInputDescription(false);
}
}, [selected]);
// State for outline color // State for outline color
const isBuilding = useFlowStore((state) => state.isBuilding); const isBuilding = useFlowStore((state) => state.isBuilding);
// should be empty string if no duration const updateNodeCode = useUpdateNodeCode(
// else should be `Duration: ${duration}` data?.id,
const getDurationString = (duration: number | undefined): string => { data.node!,
if (duration === undefined) { setNode,
return ""; setIsOutdated,
} else { updateNodeInternals
return `${duration}`; );
}
};
const durationString = getDurationString(validationStatus?.data.duration);
useEffect(() => { const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
setNodeDescription(data.node!.description);
}, [data.node!.description]);
useEffect(() => {
setNodeName(data.node!.display_name);
}, [data.node!.display_name]);
useEffect(() => {
const relevantData =
flowPool[data.id] && flowPool[data.id]?.length > 0
? flowPool[data.id][flowPool[data.id].length - 1]
: null;
if (relevantData) {
// Extract validation information from relevantData and update the validationStatus state
setValidationStatus(relevantData);
} else {
setValidationStatus(null);
}
}, [flowPool[data.id], data.id]);
useEffect(() => {
if (validationStatus?.params) {
// if it is not a string turn it into a string
let newValidationString = validationStatus.params;
if (typeof newValidationString !== "string") {
newValidationString = JSON.stringify(validationStatus.params);
}
setValidationString(newValidationString);
}
}, [validationStatus, validationStatus?.params]);
const [showNode, setShowNode] = useState(data.showNode ?? true);
useEffect(() => {
setShowNode(data.showNode ?? true);
}, [data.showNode]);
const nameEditable = true;
const isEmoji = emojiRegex().test(data?.node?.icon!);
const iconNodeRender = useCallback(() => {
const iconElement = data?.node?.icon;
const iconColor = nodeColors[types[data.type]];
const iconName =
iconElement || (data.node?.flow ? "group_components" : name);
const iconClassName = `generic-node-icon ${
!showNode ? " absolute inset-x-6 h-12 w-12 " : ""
}`;
if (iconElement && isEmoji) {
return nodeIconFragment(iconElement);
} else {
return checkNodeIconFragment(iconColor, iconName, iconClassName);
}
}, [data, isEmoji, name, showNode]);
const nodeIconFragment = (icon) => { const nodeIconFragment = (icon) => {
return <span className="text-lg">{icon}</span>; return <span className="text-lg">{icon}</span>;
@ -252,87 +112,24 @@ export default function GenericNode({
); );
}; };
const isDark = useDarkStore((state) => state.dark); const renderIconStatus = () => {
const renderIconStatus = (
buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null,
) => {
const conditionSuccess = validationStatus && validationStatus.valid;
const conditionInactive =
validationStatus &&
!validationStatus.valid &&
buildStatus === BuildStatus.INACTIVE;
const conditionError =
buildStatus === BuildStatus.ERROR ||
(validationStatus && !validationStatus.valid);
if (buildStatus === BuildStatus.BUILDING) {
return <Loading className="text-medium-indigo" />;
} else {
return ( return (
<> <div className="generic-node-status-position flex items-center justify-center">
<IconComponent {iconStatus}
name="Play" </div>
className={cn(
!conditionSuccess && !conditionInactive && !conditionError
? "opacity-100"
: "opacity-0",
"absolute ml-0.5 h-5 fill-current stroke-2 text-muted-foreground transition-all group-hover:text-medium-indigo group-hover/node:opacity-100",
)}
/>
{conditionSuccess ? (
<Checkmark
className="absolute ml-0.5 h-5 stroke-2 text-status-green opacity-100 transition-all group-hover/node:opacity-0"
isVisible={true}
/>
) : conditionInactive ? (
<IconComponent
name="Play"
className="absolute ml-0.5 h-5 fill-current stroke-2 text-status-gray opacity-30 transition-all group-hover/node:opacity-0"
/>
) : conditionError ? (
<Xmark
isVisible={true}
className="absolute ml-0.5 h-5 fill-current stroke-2 text-status-red opacity-100 transition-all group-hover/node:opacity-0"
/>
) : (
<></>
)}
</>
); );
}
};
const getSpecificClassFromBuildStatus = (
buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null,
) => {
let isInvalid = validationStatus && !validationStatus.valid;
if (buildStatus === BuildStatus.INACTIVE) {
// INACTIVE should have its own class
return "inactive-status";
}
if (
(buildStatus === BuildStatus.BUILT && isInvalid) ||
buildStatus === BuildStatus.ERROR
) {
return isDark ? "built-invalid-status-dark" : "built-invalid-status";
} else if (buildStatus === BuildStatus.BUILDING) {
return "building-status";
} else {
return "";
}
}; };
const getNodeBorderClassName = ( const getNodeBorderClassName = (
selected: boolean, selected: boolean,
showNode: boolean, showNode: boolean,
buildStatus: BuildStatus | undefined, buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null, validationStatus: VertexBuildTypeAPI | null
) => { ) => {
const specificClassFromBuildStatus = getSpecificClassFromBuildStatus( const specificClassFromBuildStatus = getSpecificClassFromBuildStatus(
buildStatus, buildStatus,
validationStatus, validationStatus,
isDark
); );
const baseBorderClass = getBaseBorderClass(selected); const baseBorderClass = getBaseBorderClass(selected);
@ -341,11 +138,13 @@ export default function GenericNode({
baseBorderClass, baseBorderClass,
nodeSizeClass, nodeSizeClass,
"generic-node-div group/node", "generic-node-div group/node",
specificClassFromBuildStatus, specificClassFromBuildStatus
); );
return names; return names;
}; };
// const [openWDoubleCLick, setOpenWDoubleCLick] = useState(false);
const getBaseBorderClass = (selected) => { const getBaseBorderClass = (selected) => {
let className = selected ? "border border-ring" : "border"; let className = selected ? "border border-ring" : "border";
let frozenClass = selected ? "border-ring-frozen" : "border-frozen"; let frozenClass = selected ? "border-ring-frozen" : "border-frozen";
@ -355,10 +154,99 @@ export default function GenericNode({
const getNodeSizeClass = (showNode) => const getNodeSizeClass = (showNode) =>
showNode ? "w-96 rounded-lg" : "w-26 h-26 rounded-full"; showNode ? "w-96 rounded-lg" : "w-26 h-26 rounded-full";
const nameEditable = true;
const isEmoji = emojiRegex().test(data?.node?.icon!);
if (!data.node!.template) {
setErrorData({
title: `Error in component ${data.node!.display_name}`,
list: [
`The component ${data.node!.display_name} has no template.`,
`Please contact the developer of the component to fix this issue.`,
],
});
takeSnapshot();
deleteNode(data.id);
}
useCheckCodeValidity(data, templates, setIsOutdated, types);
useValidationStatusString(validationStatus, setValidationString);
useUpdateValidationStatus(data?.id, flowPool, setValidationStatus);
const iconNodeRender = useIconNodeRender(
data,
types,
nodeColors,
name,
showNode,
isEmoji,
nodeIconFragment,
checkNodeIconFragment
);
function countHandles(): void {
const count = countHandlesFn(data);
setHandles(count);
}
useEffect(() => {
countHandles();
}, [data, data.node]);
useEffect(() => {
if (!selected) {
setInputName(false);
setInputDescription(false);
}
}, [selected]);
useEffect(() => {
setNodeDescription(data.node!.description);
}, [data.node!.description]);
useEffect(() => {
setNodeName(data.node!.display_name);
}, [data.node!.display_name]);
useEffect(() => {
setShowNode(data.showNode ?? true);
}, [data.showNode]);
const [loadingUpdate, setLoadingUpdate] = useState(false);
const handleUpdateCode = () => {
setLoadingUpdate(true);
takeSnapshot();
// to update we must get the code from the templates in useTypesStore
const thisNodeTemplate = templates[data.type]?.template;
// if the template does not have a code key
// return
if (!thisNodeTemplate?.code) return;
const currentCode = thisNodeTemplate.code.value;
if (data.node) {
postCustomComponent(currentCode, data.node)
.then((apiReturn) => {
const { data } = apiReturn;
if (data && updateNodeCode) {
updateNodeCode(data, currentCode, "code");
setLoadingUpdate(false);
}
})
.catch((err) => {
console.log(err);
});
}
};
const shortcuts = useShortcutsStore((state) => state.shortcuts);
const memoizedNodeToolbarComponent = useMemo(() => { const memoizedNodeToolbarComponent = useMemo(() => {
return ( return (
<NodeToolbar> <NodeToolbar>
<NodeToolbarComponent <NodeToolbarComponent
// openWDoubleClick={openWDoubleCLick}
// setOpenWDoubleClick={setOpenWDoubleCLick}
data={data} data={data}
deleteNode={(id) => { deleteNode={(id) => {
takeSnapshot(); takeSnapshot();
@ -375,8 +263,6 @@ export default function GenericNode({
showNode={showNode} showNode={showNode}
openAdvancedModal={false} openAdvancedModal={false}
onCloseAdvancedModal={() => {}} onCloseAdvancedModal={() => {}}
updateNodeCode={updateNodeCode}
isOutdated={isOutdated}
selected={selected} selected={selected}
/> />
</NodeToolbar> </NodeToolbar>
@ -392,16 +278,23 @@ export default function GenericNode({
updateNodeCode, updateNodeCode,
isOutdated, isOutdated,
selected, selected,
shortcuts,
// openWDoubleCLick,
// setOpenWDoubleCLick,
]); ]);
return ( return (
<> <>
{memoizedNodeToolbarComponent} {memoizedNodeToolbarComponent}
<div <div
// onDoubleClick={(event) => {
// if (!isWrappedWithClass(event, "nodoubleclick"))
// setOpenWDoubleCLick(true);
// }}
className={getNodeBorderClassName( className={getNodeBorderClassName(
selected, selected,
showNode, showNode,
buildStatus, buildStatus,
validationStatus, validationStatus
)} )}
> >
{data.node?.beta && showNode && ( {data.node?.beta && showNode && (
@ -470,7 +363,7 @@ export default function GenericNode({
event.preventDefault(); event.preventDefault();
}} }}
data-testid={"title-" + data.node?.display_name} data-testid={"title-" + data.node?.display_name}
className="generic-node-tooltip-div cursor-text text-primary" className="nodoubleclick generic-node-tooltip-div cursor-text text-primary"
> >
{data.node?.display_name} {data.node?.display_name}
</div> </div>
@ -532,7 +425,7 @@ export default function GenericNode({
} }
title={getFieldTitle( title={getFieldTitle(
data.node?.template!, data.node?.template!,
templateField, templateField
)} )}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
@ -560,7 +453,7 @@ export default function GenericNode({
proxy={data.node?.template[templateField].proxy} proxy={data.node?.template[templateField].proxy}
showNode={showNode} showNode={showNode}
/> />
), )
)} )}
{/* <ParameterComponent {/* <ParameterComponent
index={0} index={0}
@ -592,6 +485,23 @@ export default function GenericNode({
)} )}
</div> </div>
{showNode && ( {showNode && (
<>
<div className="flex flex-shrink-0 items-center gap-1">
{isOutdated && (
<ShadTooltip content={TOOLTIP_OUTDATED_NODE}>
<Button
onClick={handleUpdateCode}
variant="secondary"
className={"h-9 px-1.5"}
loading={loadingUpdate}
>
<IconComponent
name="AlertTriangle"
className="h-5 w-5 text-status-yellow"
/>
</Button>
</ShadTooltip>
)}
<ShadTooltip <ShadTooltip
content={ content={
buildStatus === BuildStatus.BUILDING ? ( buildStatus === BuildStatus.BUILDING ? (
@ -612,21 +522,10 @@ export default function GenericNode({
</div> </div>
<div className="justify-left flex font-normal text-muted-foreground"> <div className="justify-left flex font-normal text-muted-foreground">
<div>Duration:</div> <div>Duration:</div>
<div className="mb-3 ml-1 text-status-blue"> <div className="ml-1 text-status-blue">
{validationStatus?.data.duration} {validationStatus?.data.duration}
</div> </div>
</div> </div>
<hr />
<span className="mb-2 mt-2 flex justify-center font-semibold text-muted-foreground">
Output
</span>
<div className="max-h-96 overflow-auto font-normal custom-scroll">
{validationString.split("\n").map((line, index) => (
<div className="font-normal" key={index}>
{line}
</div>
))}
</div>
</div> </div>
) )
} }
@ -647,12 +546,12 @@ export default function GenericNode({
`button_run_` + data?.node?.display_name.toLowerCase() `button_run_` + data?.node?.display_name.toLowerCase()
} }
> >
<div className="generic-node-status-position flex items-center justify-center"> {renderIconStatus()}
{renderIconStatus(buildStatus, validationStatus)}
</div>
</div> </div>
</Button> </Button>
</ShadTooltip> </ShadTooltip>
</div>
</>
)} )}
</div> </div>
</div> </div>
@ -714,12 +613,12 @@ export default function GenericNode({
) : ( ) : (
<div <div
className={cn( className={cn(
"generic-node-desc-text cursor-text truncate-multiline word-break-break-word", "nodoubleclick generic-node-desc-text cursor-text truncate-multiline word-break-break-word",
(data.node?.description === "" || (data.node?.description === "" ||
!data.node?.description) && !data.node?.description) &&
nameEditable nameEditable
? "font-light italic" ? "font-light italic"
: "", : ""
)} )}
onClick={(e) => { onClick={(e) => {
setInputDescription(true); setInputDescription(true);
@ -781,13 +680,13 @@ export default function GenericNode({
} }
title={getFieldTitle( title={getFieldTitle(
data.node?.template!, data.node?.template!,
templateField, templateField
)} )}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
tooltipTitle={ tooltipTitle={
data.node?.template[templateField].input_types?.join( data.node?.template[templateField].input_types?.join(
"\n", "\n"
) ?? data.node?.template[templateField].type ) ?? data.node?.template[templateField].type
} }
required={data.node!.template[templateField].required} required={data.node!.template[templateField].required}
@ -814,7 +713,7 @@ export default function GenericNode({
<div <div
className={classNames( className={classNames(
Object.keys(data.node!.template).length < 1 ? "hidden" : "", Object.keys(data.node!.template).length < 1 ? "hidden" : "",
"flex-max-width justify-center", "flex-max-width justify-center"
)} )}
> >
{" "} {" "}

View file

@ -7,7 +7,7 @@ import {
CSVViewErrorTitle, CSVViewErrorTitle,
} from "../../constants/constants"; } from "../../constants/constants";
import { useDarkStore } from "../../stores/darkStore"; import { useDarkStore } from "../../stores/darkStore";
import { FlowPoolObjectType } from "../../types/chat"; import { VertexBuildTypeAPI } from "../../types/api";
import { NodeType } from "../../types/flow"; import { NodeType } from "../../types/flow";
import ForwardedIconComponent from "../genericIconComponent"; import ForwardedIconComponent from "../genericIconComponent";
import TableComponent from "../tableComponent"; import TableComponent from "../tableComponent";
@ -19,7 +19,7 @@ function CsvOutputComponent({
flowPool, flowPool,
}: { }: {
csvNode: NodeType; csvNode: NodeType;
flowPool: FlowPoolObjectType; flowPool: VertexBuildTypeAPI;
}) { }) {
const csvNodeArtifacts = flowPool?.data?.artifacts?.repr; const csvNodeArtifacts = flowPool?.data?.artifacts?.repr;
const jsonString = csvNodeArtifacts?.replace(/'/g, '"'); const jsonString = csvNodeArtifacts?.replace(/'/g, '"');

View file

@ -18,7 +18,7 @@ export default function TableOptions({
}): JSX.Element { }): JSX.Element {
return ( return (
<div className={cn("absolute bottom-3 left-6")}> <div className={cn("absolute bottom-3 left-6")}>
<div className="flex items-center gap-2"> <div className="flex items-center gap-3">
<div> <div>
<ShadTooltip content="Reset Columns"> <ShadTooltip content="Reset Columns">
<Button <Button
@ -31,7 +31,10 @@ export default function TableOptions({
> >
<IconComponent <IconComponent
name="RotateCcw" name="RotateCcw"
className={cn("h-5 w-5 text-primary transition-all")} strokeWidth={2}
className={cn(
"h-5 w-5 text-primary transition-all hover:text-accent-foreground"
)}
/> />
</Button> </Button>
</ShadTooltip> </ShadTooltip>
@ -82,7 +85,7 @@ export default function TableOptions({
name="Trash2" name="Trash2"
className={cn( className={cn(
"h-5 w-5 text-primary transition-all", "h-5 w-5 text-primary transition-all",
!hasSelection ? "" : "hover:text-destructive" !hasSelection ? "" : "hover:text-status-red "
)} )}
/> />
</Button> </Button>

View file

@ -159,6 +159,19 @@ const TableComponent = forwardRef<
}, 100); }, 100);
}} }}
/> />
<TableOptions
stateChange={columnStateChange}
hasSelection={realRef.current?.api?.getSelectedRows().length > 0}
duplicateRow={props.onDuplicate ? props.onDuplicate : undefined}
deleteRow={props.onDelete ? props.onDelete : undefined}
resetGrid={() => {
console.log("teste");
resetGrid(realRef, initialColumnDefs);
setTimeout(() => {
setColumnStateChange(false);
}, 100);
}}
/>
<ResetColumns resetGrid={() => resetGrid(realRef, initialColumnDefs)} /> <ResetColumns resetGrid={() => resetGrid(realRef, initialColumnDefs)} />
</div> </div>
); );

View file

@ -829,3 +829,9 @@ export const MAX_BATCH_SIZE = 50;
export const MODAL_CLASSES = export const MODAL_CLASSES =
"nopan nodelete nodrag noundo nocopy fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"; "nopan nodelete nodrag noundo nocopy fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0";
export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"];
export const FS_ERROR_TEXT =
"Please ensure your file has one of the following extensions:";
export const SN_ERROR_TEXT = ALLOWED_IMAGE_INPUT_EXTENSIONS.join(", ");

View file

@ -1092,20 +1092,11 @@ export async function getMessagesTable(
} }
const rows = await api.get(`${BASE_URL_API}monitor/messages`, config); const rows = await api.get(`${BASE_URL_API}monitor/messages`, config);
const columns = extractColumnsFromRows(rows.data, mode, excludedFields); const columns = extractColumnsFromRows(rows.data, mode, excludedFields);
return { rows: rows.data, columns };
}
export async function getSessions(id?: string): Promise<Array<string>> {
const config = {};
if (id) {
config["params"] = { flow_id: id };
}
const rows = await api.get(`${BASE_URL_API}monitor/messages`, config);
const sessions = new Set<string>(); const sessions = new Set<string>();
rows.data.forEach((row) => { rows.data.forEach((row) => {
sessions.add(row.session_id); sessions.add(row.session_id);
}); });
return Array.from(sessions); return { rows: rows.data, columns };
} }
export async function deleteMessagesFn(ids: number[]) { export async function deleteMessagesFn(ids: number[]) {

View file

@ -0,0 +1,24 @@
const SvgLangChainIcon = (props) => (
<svg
viewBox="0 0 81 41"
fill="none"
height="200"
width="400"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M61.514 11.157a3.94 3.94 0 0 0-2.806 1.158l-3.018 3.01a3.95 3.95 0 0 0-1.147 3.095l.019.191a3.9 3.9 0 0 0 1.128 2.314 3.6 3.6 0 0 0 1.496.9q.046.263.047.53c0 .797-.31 1.546-.874 2.107l-.186.186c-1.008-.344-1.848-.847-2.607-1.604a6.9 6.9 0 0 1-1.927-3.67l-.034-.193-.153.124a4 4 0 0 0-.294.265l-3.018 3.01a3.957 3.957 0 0 0 2.807 6.757 3.96 3.96 0 0 0 2.806-1.158l3.019-3.01a3.96 3.96 0 0 0 0-5.599 3.9 3.9 0 0 0-1.462-.92 3.25 3.25 0 0 1 .924-2.855 6.9 6.9 0 0 1 2.664 1.656 6.9 6.9 0 0 1 1.926 3.67l.035.193.153-.124q.155-.125.296-.267l3.018-3.01a3.956 3.956 0 0 0-2.808-6.756z"
fill="CurrentColor"
/>
<path
d="M59.897.149h-39.49C9.153.149 0 9.279 0 20.5c0 11.222 9.154 20.351 20.406 20.351h39.49c11.253 0 20.407-9.13 20.407-20.35C80.303 9.277 71.149.148 59.897.148M40.419 32.056c-.651.134-1.384.158-1.882-.36-.183.42-.612.199-.943.144-.03.085-.057.16-.085.246-1.1.073-1.925-1.046-2.449-1.89-1.04-.562-2.222-.904-3.285-1.492-.062.968.15 2.17-.774 2.794-.047 1.862 2.824.22 3.088 1.608-.204.022-.43-.033-.594.124-.749.726-1.608-.55-2.471-.023-1.16.582-1.276 1.059-2.71 1.179-.08-.12-.047-.2.02-.273.404-.468.433-1.02 1.122-1.22-.71-.111-1.303.28-1.901.59-.778.317-.772-.717-1.968.054-.132-.108-.069-.206.007-.289.304-.37.704-.425 1.155-.405-2.219-1.233-3.263 1.508-4.288.145-.308.081-.424.358-.618.553-.167-.183-.04-.405-.033-.62-.2-.094-.453-.139-.394-.459-.391-.132-.665.1-.957.32-.263-.203.178-.5.26-.712.234-.407.769-.084 1.04-.377.772-.437 1.847.273 2.729.153.68.085 1.52-.61 1.179-1.305-.726-.926-.598-2.137-.614-3.244-.09-.645-1.643-1.467-2.092-2.163-.555-.627-.987-1.353-1.42-2.068-1.561-3.014-1.07-6.886-3.037-9.685-.89.49-2.048.259-2.816-.399-.414.377-.432.87-.465 1.392-.994-.99-.87-2.863-.075-3.966a5.3 5.3 0 0 1 1.144-1.11c.098-.07.131-.14.129-.25.786-3.524 6.144-2.845 7.838-.348 1.229 1.537 1.6 3.57 2.994 4.997 1.875 2.047 4.012 3.85 5.742 6.03 1.637 1.992 2.806 4.328 3.826 6.683.416.782.42 1.74 1.037 2.408.304.403 1.79 1.5 1.467 1.888.186.403 1.573.959 1.092 1.35zm26.026-12.024-3.018 3.01a6.96 6.96 0 0 1-2.875 1.728l-.056.016-.02.053a6.9 6.9 0 0 1-1.585 2.446l-3.019 3.01a6.94 6.94 0 0 1-4.932 2.035 6.94 6.94 0 0 1-4.932-2.035 6.95 6.95 0 0 1 0-9.838l3.018-3.01a6.9 6.9 0 0 1 2.871-1.721l.055-.017.02-.053a6.9 6.9 0 0 1 1.59-2.454l3.019-3.01a6.94 6.94 0 0 1 4.932-2.035c1.865 0 3.616.723 4.932 2.035a6.9 6.9 0 0 1 2.04 4.92c0 1.86-.724 3.607-2.04 4.918z"
fill="CurrentColor"
/>
<path
d="M28.142 28.413c-.265 1.03-.35 2.782-1.694 2.832-.11.595.413.819.89.627.472-.215.696.171.855.556.729.106 1.806-.242 1.847-1.103-1.088-.625-1.424-1.813-1.896-2.914z"
fill="CurrentColor"
/>
</svg>
);
export default SvgLangChainIcon;

View file

@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import SvgLangChainIcon from "./LangChainIcon";
export const LangChainIcon = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
return <SvgLangChainIcon ref={ref} {...props} />;
});

View file

@ -0,0 +1,5 @@
<svg viewBox="0 0 81 41" fill="none" height="200" width="400" xmlns="http://www.w3.org/2000/svg">
<path d="M61.514 11.157a3.94 3.94 0 0 0-2.806 1.158l-3.018 3.01a3.95 3.95 0 0 0-1.147 3.095l.019.191a3.9 3.9 0 0 0 1.128 2.314 3.6 3.6 0 0 0 1.496.9q.046.263.047.53c0 .797-.31 1.546-.874 2.107l-.186.186c-1.008-.344-1.848-.847-2.607-1.604a6.9 6.9 0 0 1-1.927-3.67l-.034-.193-.153.124a4 4 0 0 0-.294.265l-3.018 3.01a3.957 3.957 0 0 0 2.807 6.757 3.96 3.96 0 0 0 2.806-1.158l3.019-3.01a3.96 3.96 0 0 0 0-5.599 3.9 3.9 0 0 0-1.462-.92 3.25 3.25 0 0 1 .924-2.855 6.9 6.9 0 0 1 2.664 1.656 6.9 6.9 0 0 1 1.926 3.67l.035.193.153-.124q.155-.125.296-.267l3.018-3.01a3.956 3.956 0 0 0-2.808-6.756z" fill="CurrentColor"/>
<path d="M59.897.149h-39.49C9.153.149 0 9.279 0 20.5c0 11.222 9.154 20.351 20.406 20.351h39.49c11.253 0 20.407-9.13 20.407-20.35C80.303 9.277 71.149.148 59.897.148M40.419 32.056c-.651.134-1.384.158-1.882-.36-.183.42-.612.199-.943.144-.03.085-.057.16-.085.246-1.1.073-1.925-1.046-2.449-1.89-1.04-.562-2.222-.904-3.285-1.492-.062.968.15 2.17-.774 2.794-.047 1.862 2.824.22 3.088 1.608-.204.022-.43-.033-.594.124-.749.726-1.608-.55-2.471-.023-1.16.582-1.276 1.059-2.71 1.179-.08-.12-.047-.2.02-.273.404-.468.433-1.02 1.122-1.22-.71-.111-1.303.28-1.901.59-.778.317-.772-.717-1.968.054-.132-.108-.069-.206.007-.289.304-.37.704-.425 1.155-.405-2.219-1.233-3.263 1.508-4.288.145-.308.081-.424.358-.618.553-.167-.183-.04-.405-.033-.62-.2-.094-.453-.139-.394-.459-.391-.132-.665.1-.957.32-.263-.203.178-.5.26-.712.234-.407.769-.084 1.04-.377.772-.437 1.847.273 2.729.153.68.085 1.52-.61 1.179-1.305-.726-.926-.598-2.137-.614-3.244-.09-.645-1.643-1.467-2.092-2.163-.555-.627-.987-1.353-1.42-2.068-1.561-3.014-1.07-6.886-3.037-9.685-.89.49-2.048.259-2.816-.399-.414.377-.432.87-.465 1.392-.994-.99-.87-2.863-.075-3.966a5.3 5.3 0 0 1 1.144-1.11c.098-.07.131-.14.129-.25.786-3.524 6.144-2.845 7.838-.348 1.229 1.537 1.6 3.57 2.994 4.997 1.875 2.047 4.012 3.85 5.742 6.03 1.637 1.992 2.806 4.328 3.826 6.683.416.782.42 1.74 1.037 2.408.304.403 1.79 1.5 1.467 1.888.186.403 1.573.959 1.092 1.35zm26.026-12.024-3.018 3.01a6.96 6.96 0 0 1-2.875 1.728l-.056.016-.02.053a6.9 6.9 0 0 1-1.585 2.446l-3.019 3.01a6.94 6.94 0 0 1-4.932 2.035 6.94 6.94 0 0 1-4.932-2.035 6.95 6.95 0 0 1 0-9.838l3.018-3.01a6.9 6.9 0 0 1 2.871-1.721l.055-.017.02-.053a6.9 6.9 0 0 1 1.59-2.454l3.019-3.01a6.94 6.94 0 0 1 4.932-2.035c1.865 0 3.616.723 4.932 2.035a6.9 6.9 0 0 1 2.04 4.92c0 1.86-.724 3.607-2.04 4.918z" fill="CurrentColor"/>
<path d="M28.142 28.413c-.265 1.03-.35 2.782-1.694 2.832-.11.595.413.819.89.627.472-.215.696.171.855.556.729.106 1.806-.242 1.847-1.103-1.088-.625-1.424-1.813-1.896-2.914z" fill="CurrentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -49,8 +49,6 @@ export default function IOFieldView({
(flowPool[node!.id] ?? [])[(flowPool[node!.id]?.length ?? 1) - 1]?.data (flowPool[node!.id] ?? [])[(flowPool[node!.id]?.length ?? 1) - 1]?.data
.results.result ?? ""; .results.result ?? "";
console.log(flowPoolNode?.data?.artifacts?.records);
function handleOutputType() { function handleOutputType() {
if (!node) return <>"No node found!"</>; if (!node) return <>"No node found!"</>;
switch (type) { switch (type) {
@ -252,7 +250,11 @@ export default function IOFieldView({
<div className={left ? "h-56" : "h-full"}> <div className={left ? "h-56" : "h-full"}>
<RecordsOutputComponent <RecordsOutputComponent
pagination={!left} pagination={!left}
rows={flowPoolNode?.data?.artifacts?.records ?? []} rows={
flowPoolNode?.data?.artifacts?.map(
(artifact) => artifact.data
) ?? []
}
columnMode="union" columnMode="union"
/> />
</div> </div>

View file

@ -1,9 +1,7 @@
import ShortUniqueId from "short-unique-id"; import ShortUniqueId from "short-unique-id";
import { ALLOWED_IMAGE_INPUT_EXTENSIONS, FS_ERROR_TEXT, SN_ERROR_TEXT } from "../../../../../../constants/constants";
import useFileUpload from "./use-file-upload"; import useFileUpload from "./use-file-upload";
const fsErrorText =
"Please ensure your file has one of the following extensions:";
const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp";
const useDragAndDrop = ( const useDragAndDrop = (
setIsDragging, setIsDragging,
@ -48,14 +46,16 @@ const useDragAndDrop = (
const handleFiles = (files, setFiles, currentFlowId, setErrorData) => { const handleFiles = (files, setFiles, currentFlowId, setErrorData) => {
if (files) { if (files) {
const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"];
const file = files?.[0]; const file = files?.[0];
const fileExtension = file.name.split(".").pop()?.toLowerCase(); const fileExtension = file.name.split(".").pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(fileExtension)) { if (
!fileExtension ||
!ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension)
) {
console.log("Error uploading file"); console.log("Error uploading file");
setErrorData({ setErrorData({
title: "Error uploading file", title: "Error uploading file",
list: [fsErrorText, snErrorTxt], list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
}); });
return; return;
} }

View file

@ -1,11 +1,12 @@
import ShortUniqueId from "short-unique-id"; import ShortUniqueId from "short-unique-id";
import {
ALLOWED_IMAGE_INPUT_EXTENSIONS,
FS_ERROR_TEXT,
SN_ERROR_TEXT,
} from "../../../../../../constants/constants";
import useAlertStore from "../../../../../../stores/alertStore"; import useAlertStore from "../../../../../../stores/alertStore";
import useFileUpload from "./use-file-upload"; import useFileUpload from "./use-file-upload";
const fsErrorText =
"Please ensure your file has one of the following extensions:";
const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp";
export const useHandleFileChange = (setFiles, currentFlowId) => { export const useHandleFileChange = (setFiles, currentFlowId) => {
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const handleFileChange = async ( const handleFileChange = async (
@ -14,13 +15,15 @@ export const useHandleFileChange = (setFiles, currentFlowId) => {
const fileInput = event.target; const fileInput = event.target;
const file = fileInput.files?.[0]; const file = fileInput.files?.[0];
if (file) { if (file) {
const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"];
const fileExtension = file.name.split(".").pop()?.toLowerCase(); const fileExtension = file.name.split(".").pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(fileExtension)) { if (
!fileExtension ||
!ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension)
) {
setErrorData({ setErrorData({
title: "Error uploading file", title: "Error uploading file",
list: [fsErrorText, snErrorTxt], list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
}); });
return; return;
} }

View file

@ -1,12 +1,13 @@
import { useEffect } from "react"; import { useEffect } from "react";
import ShortUniqueId from "short-unique-id"; import ShortUniqueId from "short-unique-id";
import {
ALLOWED_IMAGE_INPUT_EXTENSIONS,
FS_ERROR_TEXT,
SN_ERROR_TEXT,
} from "../../../../../../constants/constants";
import useAlertStore from "../../../../../../stores/alertStore"; import useAlertStore from "../../../../../../stores/alertStore";
import useFileUpload from "./use-file-upload"; import useFileUpload from "./use-file-upload";
const fsErrorText =
"Please ensure your file has one of the following extensions:";
const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp";
const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => { const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => {
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
useEffect(() => { useEffect(() => {
@ -21,20 +22,15 @@ const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => {
const uid = new ShortUniqueId({ length: 3 }); const uid = new ShortUniqueId({ length: 3 });
const blob = items[i].getAsFile(); const blob = items[i].getAsFile();
if (blob) { if (blob) {
const allowedExtensions = [
"png",
"jpg",
"jpeg",
"gif",
"bmp",
"webp",
];
const fileExtension = blob.name.split(".").pop()?.toLowerCase(); const fileExtension = blob.name.split(".").pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(fileExtension)) { if (
!fileExtension ||
!ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension)
) {
setErrorData({ setErrorData({
title: "Error uploading file", title: "Error uploading file",
list: [fsErrorText, snErrorTxt], list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
}); });
return; return;
} }

View file

@ -2,7 +2,6 @@ import { ColDef, ValueGetterParams } from "ag-grid-community";
import { useMemo } from "react"; import { useMemo } from "react";
import TableNodeCellRender from "../../../components/tableComponent/components/tableNodeCellRender"; import TableNodeCellRender from "../../../components/tableComponent/components/tableNodeCellRender";
import TableToggleCellRender from "../../../components/tableComponent/components/tableToggleCellRender"; import TableToggleCellRender from "../../../components/tableComponent/components/tableToggleCellRender";
import TableTooltipRender from "../../../components/tableComponent/components/tableTooltipRender";
const useColumnDefs = ( const useColumnDefs = (
myData: any, myData: any,
@ -23,8 +22,6 @@ const useColumnDefs = (
: templateParam.name) ?? params.data.key : templateParam.name) ?? params.data.key
); );
}, },
tooltipField: "display_name",
tooltipComponent: TableTooltipRender,
wrapText: true, wrapText: true,
autoHeight: true, autoHeight: true,
flex: 1, flex: 1,
@ -35,7 +32,6 @@ const useColumnDefs = (
headerName: "Description", headerName: "Description",
field: "info", field: "info",
tooltipField: "info", tooltipField: "info",
tooltipComponent: TableTooltipRender,
wrapText: true, wrapText: true,
autoHeight: true, autoHeight: true,
flex: 2, flex: 2,

View file

@ -3,6 +3,7 @@ import { forwardRef, useEffect, useRef, useState } from "react";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import TableComponent from "../../components/tableComponent"; import TableComponent from "../../components/tableComponent";
import { Badge } from "../../components/ui/badge"; import { Badge } from "../../components/ui/badge";
import { useDarkStore } from "../../stores/darkStore";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import { NodeDataType } from "../../types/flow"; import { NodeDataType } from "../../types/flow";
import BaseModal from "../baseModal"; import BaseModal from "../baseModal";
@ -28,6 +29,8 @@ const EditNodeModal = forwardRef(
) => { ) => {
const myData = useRef(data); const myData = useRef(data);
const isDark = useDarkStore((state) => state.dark);
const setNode = useFlowStore((state) => state.setNode); const setNode = useFlowStore((state) => state.setNode);
function changeAdvanced(n) { function changeAdvanced(n) {
@ -57,6 +60,12 @@ const EditNodeModal = forwardRef(
} }
}, [gridApi, open]); }, [gridApi, open]);
// useEffect(() => {
// return () => {
// setOpenWDoubleClick(false);
// };
// }, []);
return ( return (
<BaseModal <BaseModal
key={data.id} key={data.id}
@ -79,7 +88,9 @@ const EditNodeModal = forwardRef(
</BaseModal.Trigger> </BaseModal.Trigger>
<BaseModal.Header description={data.node?.description!}> <BaseModal.Header description={data.node?.description!}>
<span className="pr-2">{data.type}</span> <span className="pr-2">{data.type}</span>
<Badge variant="secondary">ID: {data.id}</Badge> <Badge variant={isDark ? "gray" : "secondary"}>
<span className="relative top-[0.6px]">ID: {data.id}</span>
</Badge>
</BaseModal.Header> </BaseModal.Header>
<BaseModal.Content> <BaseModal.Content>
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">

View file

@ -179,6 +179,7 @@ export default function Page({
function handleUndo(e: KeyboardEvent) { function handleUndo(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if (!isWrappedWithClass(e, "noundo")) { if (!isWrappedWithClass(e, "noundo")) {
undo(); undo();
} }
@ -186,6 +187,7 @@ export default function Page({
function handleRedo(e: KeyboardEvent) { function handleRedo(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if (!isWrappedWithClass(e, "noundo")) { if (!isWrappedWithClass(e, "noundo")) {
redo(); redo();
} }
@ -193,6 +195,7 @@ export default function Page({
function handleGroup(e: KeyboardEvent) { function handleGroup(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if (selectionMenuVisible) { if (selectionMenuVisible) {
handleGroupNode(); handleGroupNode();
} }
@ -201,6 +204,7 @@ export default function Page({
function handleDuplicate(e: KeyboardEvent) { function handleDuplicate(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
e.stopImmediatePropagation();
const selectedNode = nodes.filter((obj) => obj.selected); const selectedNode = nodes.filter((obj) => obj.selected);
if (selectedNode.length > 0) { if (selectedNode.length > 0) {
paste( paste(
@ -215,6 +219,7 @@ export default function Page({
function handleCopy(e: KeyboardEvent) { function handleCopy(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if ( if (
!isWrappedWithClass(e, "nocopy") && !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 && window.getSelection()?.toString().length === 0 &&
@ -226,6 +231,7 @@ export default function Page({
function handleCut(e: KeyboardEvent) { function handleCut(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if ( if (
!isWrappedWithClass(e, "nocopy") && !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 && window.getSelection()?.toString().length === 0 &&
@ -237,6 +243,7 @@ export default function Page({
function handlePaste(e: KeyboardEvent) { function handlePaste(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if ( if (
!isWrappedWithClass(e, "nocopy") && !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 && window.getSelection()?.toString().length === 0 &&
@ -252,6 +259,7 @@ export default function Page({
function handleDelete(e: KeyboardEvent) { function handleDelete(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation();
if (!isWrappedWithClass(e, "nodelete") && lastSelection) { if (!isWrappedWithClass(e, "nodelete") && lastSelection) {
takeSnapshot(); takeSnapshot();
deleteNode(lastSelection.nodes.map((node) => node.id)); deleteNode(lastSelection.nodes.map((node) => node.id));

View file

@ -7,7 +7,6 @@ import IconComponent from "../../../../components/genericIconComponent";
import PaginatorComponent from "../../../../components/paginatorComponent"; import PaginatorComponent from "../../../../components/paginatorComponent";
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent"; import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
import { Button } from "../../../../components/ui/button"; import { Button } from "../../../../components/ui/button";
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal"; import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal";
import useAlertStore from "../../../../stores/alertStore"; import useAlertStore from "../../../../stores/alertStore";
import { useDarkStore } from "../../../../stores/darkStore"; import { useDarkStore } from "../../../../stores/darkStore";
@ -113,104 +112,6 @@ export default function ComponentsComponent({
setValue setValue
); );
const handleSelectOptionsChange = (action: string) => {
const hasSelected = selectedFlowsComponentsCards?.length > 0;
if (!hasSelected) {
setErrorData({
title: "No items selected",
list: ["Please select items to delete"],
});
return;
}
if (action === "delete") {
setOpenDelete(true);
} else if (action === "duplicate") {
handleDuplicate();
} else if (action === "export") {
handleExport();
}
};
const handleDuplicate = () => {
Promise.all(
selectedFlowsComponentsCards.map((selectedFlow) =>
addFlow(
true,
allFlows.find((flow) => flow.id === selectedFlow)
)
)
).then(() => {
resetFilter();
getFoldersApi(true);
if (!folderId || folderId === myCollectionId) {
getFolderById(folderId ? folderId : myCollectionId);
}
setSelectedFlowsComponentsCards([]);
setSuccessData({ title: "Flows duplicated successfully" });
});
};
const handleImport = () => {
uploadFlow({ newProject: true, isComponent: false })
.then(() => {
resetFilter();
getFoldersApi(true);
if (!folderId || folderId === myCollectionId) {
getFolderById(folderId ? folderId : myCollectionId);
}
setSelectedFlowsComponentsCards([]);
setSuccessData({ title: "Flows imported successfully" });
})
.catch((error) => {
setErrorData({
title: UPLOAD_ERROR_ALERT,
list: [error],
});
});
};
const version = useDarkStore((state) => state.version);
const handleExport = () => {
selectedFlowsComponentsCards.map((selectedFlowId) => {
const selectedFlow = allFlows.find((flow) => flow.id === selectedFlowId);
downloadFlow(
removeApiKeys({
id: selectedFlow!.id,
data: selectedFlow!.data!,
description: selectedFlow!.description,
name: selectedFlow!.name,
last_tested_version: version,
is_component: false,
}),
selectedFlow!.name,
selectedFlow!.description
);
});
setSuccessData({ title: "Flows exported successfully" });
};
const handleDeleteMultiple = () => {
removeFlow(selectedFlowsComponentsCards)
.then(() => {
resetFilter();
getFoldersApi(true);
if (!folderId || folderId === myCollectionId) {
getFolderById(folderId ? folderId : myCollectionId);
}
setSuccessData({
title: "Selected items deleted successfully",
});
})
.catch(() => {
setErrorData({
title: "Error deleting items",
list: ["Please try again"],
});
});
};
const { handleDuplicate } = useDuplicateFlows( const { handleDuplicate } = useDuplicateFlows(
selectedFlowsComponentsCards, selectedFlowsComponentsCards,
addFlow, addFlow,

View file

@ -107,7 +107,7 @@ const HeaderComponent = ({
name="Trash2" name="Trash2"
className={cn( className={cn(
"h-5 w-5 text-primary transition-all", "h-5 w-5 text-primary transition-all",
disableFunctions ? "" : "hover:text-destructive" disableFunctions ? "" : "hover:text-status-red"
)} )}
/> />
</Button> </Button>

View file

@ -1,15 +1,6 @@
import ForwardedIconComponent from "../../../../../../components/genericIconComponent"; import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
import { Button } from "../../../../../../components/ui/button";
import { cn } from "../../../../../../utils/utils";
type HeaderMessagesComponentProps = { const HeaderMessagesComponent = () => {
selectedRows: number[];
handleRemoveMessages: () => void;
};
const HeaderMessagesComponent = ({
selectedRows,
handleRemoveMessages,
}: HeaderMessagesComponentProps) => {
return ( return (
<> <>
<div className="flex w-full items-center justify-between gap-4 space-y-0.5"> <div className="flex w-full items-center justify-between gap-4 space-y-0.5">
@ -26,22 +17,6 @@ const HeaderMessagesComponent = ({
behaviors. behaviors.
</p> </p>
</div> </div>
<div className="flex flex-shrink-0 items-center gap-2">
<Button
data-testid="api-key-button-store"
variant="primary"
className="group px-2"
disabled={selectedRows.length === 0}
onClick={handleRemoveMessages}
>
<ForwardedIconComponent
name="Trash2"
className={cn(
"h-5 w-5 text-destructive group-disabled:text-primary"
)}
/>
</Button>
</div>
</div> </div>
</> </>
); );

View file

@ -46,10 +46,7 @@ export default function MessagesPage() {
return ( return (
<div className="flex h-full w-full flex-col justify-between gap-6"> <div className="flex h-full w-full flex-col justify-between gap-6">
<HeaderMessagesComponent <HeaderMessagesComponent />
selectedRows={selectedRows}
handleRemoveMessages={handleRemoveMessages}
/>
<div className="flex h-full w-full flex-col justify-between"> <div className="flex h-full w-full flex-col justify-between">
<TableComponent <TableComponent

View file

@ -85,7 +85,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
readFlowsFromDatabase() readFlowsFromDatabase()
.then((dbData) => { .then((dbData) => {
if (dbData) { if (dbData) {
const { data, flows } = processFlows(dbData, false); const { data, flows } = processFlows(dbData);
const examples = flows.filter( const examples = flows.filter(
(flow) => flow.folder_id === starterFolderId (flow) => flow.folder_id === starterFolderId
); );

View file

@ -23,7 +23,7 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
group: "mod+g", group: "mod+g",
cut: "mod+x", cut: "mod+x",
paste: "mod+v", paste: "mod+v",
api: "mod+r", api: "mod+shift+r",
update: "mod+u", update: "mod+u",
download: "mod+j", download: "mod+j",
freeze: "mod+f", freeze: "mod+f",

View file

@ -129,6 +129,7 @@ export type FlowStoreType = {
stopNodeId?: string; stopNodeId?: string;
input_value?: string; input_value?: string;
files?: string[]; files?: string[];
silent?: boolean;
}) => Promise<void>; }) => Promise<void>;
getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport }; getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport };
updateVerticesBuild: ( updateVerticesBuild: (

View file

@ -176,6 +176,7 @@ import {
import { GroqIcon } from "../icons/Groq"; import { GroqIcon } from "../icons/Groq";
import { HuggingFaceIcon } from "../icons/HuggingFace"; import { HuggingFaceIcon } from "../icons/HuggingFace";
import { IFixIcon } from "../icons/IFixIt"; import { IFixIcon } from "../icons/IFixIt";
import { LangChainIcon } from "../icons/LangChain";
import { MetaIcon } from "../icons/Meta"; import { MetaIcon } from "../icons/Meta";
import { MidjourneyIcon } from "../icons/Midjorney"; import { MidjourneyIcon } from "../icons/Midjorney";
import { MongoDBIcon } from "../icons/MongoDB"; import { MongoDBIcon } from "../icons/MongoDB";
@ -324,6 +325,7 @@ export const nodeIconsLucide: iconsType = {
ChatOllamaModel: OllamaIcon, ChatOllamaModel: OllamaIcon,
Faiss: MetaIcon, Faiss: MetaIcon,
FaissSearch: MetaIcon, FaissSearch: MetaIcon,
LangChain: LangChainIcon,
AzureOpenAiModel: AzureIcon, AzureOpenAiModel: AzureIcon,
Redis: RedisIcon, Redis: RedisIcon,
RedisSearch: RedisIcon, RedisSearch: RedisIcon,

View file

@ -237,6 +237,10 @@ module.exports = {
".text-align-last-right": { ".text-align-last-right": {
"text-align-last": "right", "text-align-last": "right",
}, },
":focus-visible": {
outline: "none !important",
outlineOffset: "0px !important",
},
}); });
}), }),
require("@tailwindcss/typography"), require("@tailwindcss/typography"),

View file

@ -90,6 +90,8 @@ test("search components", async ({ page }) => {
await page.getByRole("heading", { name: "Basic Prompting" }).click(); await page.getByRole("heading", { name: "Basic Prompting" }).click();
await page.getByText("Chat Input").first().click(); await page.getByText("Chat Input").first().click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("icon-SaveAll").first().click(); await page.getByTestId("icon-SaveAll").first().click();
await page.keyboard.press("Escape"); await page.keyboard.press("Escape");
await page await page
@ -98,6 +100,8 @@ test("search components", async ({ page }) => {
}) })
.first() .first()
.click(); .click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("icon-SaveAll").first().click(); await page.getByTestId("icon-SaveAll").first().click();
await page.keyboard.press("Escape"); await page.keyboard.press("Escape");
@ -107,6 +111,8 @@ test("search components", async ({ page }) => {
}) })
.first() .first()
.click(); .click();
await page.getByTestId("more-options-modal").click();
await page.getByTestId("icon-SaveAll").first().click(); await page.getByTestId("icon-SaveAll").first().click();
await page.keyboard.press("Escape"); await page.keyboard.press("Escape");
await page.getByTestId("icon-ChevronLeft").first().click(); await page.getByTestId("icon-ChevronLeft").first().click();

View file

@ -44,9 +44,7 @@
"name": "input_value", "name": "input_value",
"display_name": "Message", "display_name": "Message",
"advanced": false, "advanced": false,
"input_types": [ "input_types": ["Text"],
"Text"
],
"dynamic": false, "dynamic": false,
"info": "", "info": "",
"load_from_db": false, "load_from_db": false,
@ -70,9 +68,7 @@
"info": "In case of Message being a Record, this template will be used to convert it to text.", "info": "In case of Message being a Record, this template will be used to convert it to text.",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"return_record": { "return_record": {
"type": "bool", "type": "bool",
@ -104,10 +100,7 @@
"fileTypes": [], "fileTypes": [],
"file_path": "", "file_path": "",
"password": false, "password": false,
"options": [ "options": ["Machine", "User"],
"Machine",
"User"
],
"name": "sender", "name": "sender",
"display_name": "Sender Type", "display_name": "Sender Type",
"advanced": true, "advanced": true,
@ -115,9 +108,7 @@
"info": "", "info": "",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"sender_name": { "sender_name": {
"type": "str", "type": "str",
@ -137,9 +128,7 @@
"info": "", "info": "",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"session_id": { "session_id": {
"type": "str", "type": "str",
@ -158,20 +147,13 @@
"info": "If provided, the message will be stored in the memory.", "info": "If provided, the message will be stored in the memory.",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"_type": "CustomComponent" "_type": "CustomComponent"
}, },
"description": "Display a chat message in the Playground.", "description": "Display a chat message in the Playground.",
"icon": "ChatOutput", "icon": "ChatOutput",
"base_classes": [ "base_classes": ["object", "Record", "str", "Text"],
"object",
"Record",
"str",
"Text"
],
"display_name": "Chat Output", "display_name": "Chat Output",
"documentation": "", "documentation": "",
"custom_fields": { "custom_fields": {
@ -182,10 +164,7 @@
"return_record": null, "return_record": null,
"record_template": null "record_template": null
}, },
"output_types": [ "output_types": ["Text", "Record"],
"Text",
"Record"
],
"field_formatters": {}, "field_formatters": {},
"frozen": false, "frozen": false,
"field_order": [], "field_order": [],
@ -280,10 +259,7 @@
"fileTypes": [], "fileTypes": [],
"file_path": "", "file_path": "",
"password": false, "password": false,
"options": [ "options": ["Machine", "User"],
"Machine",
"User"
],
"name": "sender", "name": "sender",
"display_name": "Sender Type", "display_name": "Sender Type",
"advanced": true, "advanced": true,
@ -291,9 +267,7 @@
"info": "", "info": "",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"sender_name": { "sender_name": {
"type": "str", "type": "str",
@ -313,9 +287,7 @@
"info": "", "info": "",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"session_id": { "session_id": {
"type": "str", "type": "str",
@ -334,20 +306,13 @@
"info": "If provided, the message will be stored in the memory.", "info": "If provided, the message will be stored in the memory.",
"load_from_db": false, "load_from_db": false,
"title_case": false, "title_case": false,
"input_types": [ "input_types": ["Text"]
"Text"
]
}, },
"_type": "CustomComponent" "_type": "CustomComponent"
}, },
"description": "Get chat inputs from the Playground.", "description": "Get chat inputs from the Playground.",
"icon": "ChatInput", "icon": "ChatInput",
"base_classes": [ "base_classes": ["object", "Record", "str", "Text"],
"object",
"Record",
"str",
"Text"
],
"display_name": "Chat Input", "display_name": "Chat Input",
"documentation": "", "documentation": "",
"custom_fields": { "custom_fields": {
@ -357,10 +322,7 @@
"session_id": null, "session_id": null,
"return_record": null "return_record": null
}, },
"output_types": [ "output_types": ["Text", "Record"],
"Text",
"Record"
],
"field_formatters": {}, "field_formatters": {},
"frozen": false, "frozen": false,
"field_order": [], "field_order": [],
@ -383,18 +345,11 @@
"targetHandle": { "targetHandle": {
"fieldName": "input_value", "fieldName": "input_value",
"id": "ChatOutput-xPeM1", "id": "ChatOutput-xPeM1",
"inputTypes": [ "inputTypes": ["Text"],
"Text"
],
"type": "str" "type": "str"
}, },
"sourceHandle": { "sourceHandle": {
"baseClasses": [ "baseClasses": ["object", "Record", "str", "Text"],
"object",
"Record",
"str",
"Text"
],
"dataType": "ChatInput", "dataType": "ChatInput",
"id": "ChatInput-XYvUc" "id": "ChatInput-XYvUc"
} }

View file

@ -58,7 +58,7 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
.getByTestId("textarea-input_value") .getByTestId("textarea-input_value")
.nth(1) .nth(1)
.fill( .fill(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!", "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!"
); );
await page.getByTestId("icon-LucideSend").click(); await page.getByTestId("icon-LucideSend").click();
await page.getByText("Close", { exact: true }).click(); await page.getByText("Close", { exact: true }).click();
@ -89,9 +89,9 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
await page await page
.getByText( .getByText(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!", "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!",
{ exact: true }, { exact: true }
) )
.isVisible(), .isVisible()
); );
}); });
@ -197,7 +197,7 @@ test("user must be able to send an image on chat", async ({ page }) => {
await page.getByTestId("edit-button-modal").click(); await page.getByTestId("edit-button-modal").click();
await page.getByTestId("toggle-edit-return_record").click(); await page.getByTestId("toggle-edit-return_record").click();
expect( expect(
await page.getByTestId("toggle-edit-return_record").isChecked(), await page.getByTestId("toggle-edit-return_record").isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes").click(); await page.getByText("Save Changes").click();
@ -205,7 +205,7 @@ test("user must be able to send an image on chat", async ({ page }) => {
const jsonContent = readFileSync( const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/chain.png", "src/frontend/tests/end-to-end/assets/chain.png",
"utf-8", "utf-8"
); );
// Create the DataTransfer and File // Create the DataTransfer and File

View file

@ -23,7 +23,7 @@ test("curl_api_generation", async ({ page, context }) => {
await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click(); await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() => const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText(), navigator.clipboard.readText()
); );
const clipboardContent = await handle.jsonValue(); const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0); expect(clipboardContent.length).toBeGreaterThan(0);

View file

@ -27,7 +27,7 @@ test.describe("drag and drop test", () => {
// Read your file into a buffer. // Read your file into a buffer.
const jsonContent = readFileSync( const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/collection.json", "src/frontend/tests/end-to-end/assets/collection.json",
"utf-8", "utf-8"
); );
// Create the DataTransfer and File // Create the DataTransfer and File
@ -47,7 +47,7 @@ test.describe("drag and drop test", () => {
"drop", "drop",
{ {
dataTransfer, dataTransfer,
}, }
); );
const genericNoda = page.getByTestId("div-generic-node"); const genericNoda = page.getByTestId("div-generic-node");

View file

@ -80,32 +80,32 @@ test("dropDownComponent", async ({ page }) => {
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showendpoint_url"]').click(); await page.locator('//*[@id="showendpoint_url"]').click();
expect( expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(), await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showendpoint_url"]').click(); await page.locator('//*[@id="showendpoint_url"]').click();
expect( expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(), await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showregion_name"]').click(); await page.locator('//*[@id="showregion_name"]').click();
expect( expect(
await page.locator('//*[@id="showregion_name"]').isChecked(), await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showregion_name"]').click(); await page.locator('//*[@id="showregion_name"]').click();
expect( expect(
await page.locator('//*[@id="showregion_name"]').isChecked(), await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showmodel_id // showmodel_id
@ -115,7 +115,7 @@ test("dropDownComponent", async ({ page }) => {
// showmodel_id // showmodel_id
await page.locator('//*[@id="showmodel_id"]').click(); await page.locator('//*[@id="showmodel_id"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_id"]').isChecked(), await page.locator('//*[@id="showmodel_id"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showcache"]').click(); await page.locator('//*[@id="showcache"]').click();
@ -126,32 +126,32 @@ test("dropDownComponent", async ({ page }) => {
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showendpoint_url"]').click(); await page.locator('//*[@id="showendpoint_url"]').click();
expect( expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(), await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showendpoint_url"]').click(); await page.locator('//*[@id="showendpoint_url"]').click();
expect( expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(), await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showregion_name"]').click(); await page.locator('//*[@id="showregion_name"]').click();
expect( expect(
await page.locator('//*[@id="showregion_name"]').isChecked(), await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showregion_name"]').click(); await page.locator('//*[@id="showregion_name"]').click();
expect( expect(
await page.locator('//*[@id="showregion_name"]').isChecked(), await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showmodel_id // showmodel_id
@ -161,7 +161,7 @@ test("dropDownComponent", async ({ page }) => {
// showmodel_id // showmodel_id
await page.locator('//*[@id="showmodel_id"]').click(); await page.locator('//*[@id="showmodel_id"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_id"]').isChecked(), await page.locator('//*[@id="showmodel_id"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("dropdown-edit-model_id").click(); await page.getByTestId("dropdown-edit-model_id").click();

View file

@ -64,7 +64,7 @@ test("dropDownComponent", async ({ page }) => {
// Click and hold on the first element // Click and hold on the first element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div'
) )
.hover(); .hover();
await page.mouse.down(); await page.mouse.down();
@ -72,7 +72,7 @@ test("dropDownComponent", async ({ page }) => {
// Move to the second element // Move to the second element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div'
) )
.hover(); .hover();

View file

@ -40,7 +40,7 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div', '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div'
) )
.hover() .hover()
.then(async () => { .then(async () => {
@ -60,17 +60,17 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page.getByTitle("zoom out").click(); await page.getByTitle("zoom out").click();
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div', '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
) )
.hover() .hover()
.then(async () => { .then(async () => {
await expect( await expect(
page.getByTestId("tooltip-Model Specs").first(), page.getByTestId("tooltip-Model Specs").first()
).toBeVisible(); ).toBeVisible();
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
await expect( await expect(
page.getByTestId("tooltip-Model Specs").first(), page.getByTestId("tooltip-Model Specs").first()
).toBeVisible(); ).toBeVisible();
await page.getByTestId("icon-Search").click(); await page.getByTestId("icon-Search").click();
@ -81,12 +81,12 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[5]/div/button/div/div', '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[5]/div/button/div/div'
) )
.hover() .hover()
.then(async () => { .then(async () => {
await expect( await expect(
page.getByTestId("empty-tooltip-filter").first(), page.getByTestId("empty-tooltip-filter").first()
).toBeVisible(); ).toBeVisible();
}); });
}); });
@ -113,7 +113,7 @@ test("LLMChain - Filter", async ({ page }) => {
await page.waitForTimeout(1000); await page.waitForTimeout(1000);
await page.getByTestId( await page.getByTestId(
"input-list-plus-btn-edit_metadata_indexing_include-2", "input-list-plus-btn-edit_metadata_indexing_include-2"
); );
await page.getByTestId("blank-flow").click(); await page.getByTestId("blank-flow").click();
@ -136,7 +136,7 @@ test("LLMChain - Filter", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
) )
.click(); .click();
@ -149,14 +149,14 @@ test("LLMChain - Filter", async ({ page }) => {
await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible(); await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible();
await expect(page.getByTestId("model_specsChatVertexAI")).toBeVisible(); await expect(page.getByTestId("model_specsChatVertexAI")).toBeVisible();
await expect( await expect(
page.getByTestId("model_specsGoogle Generative AI"), page.getByTestId("model_specsGoogle Generative AI")
).toBeVisible(); ).toBeVisible();
await expect( await expect(
page.getByTestId("model_specsHugging Face Inference API"), page.getByTestId("model_specsHugging Face Inference API")
).toBeVisible(); ).toBeVisible();
await expect(page.getByTestId("model_specsOllama")).toBeVisible(); await expect(page.getByTestId("model_specsOllama")).toBeVisible();
await expect( await expect(
page.getByTestId("model_specsQianfanChatEndpoint"), page.getByTestId("model_specsQianfanChatEndpoint")
).toBeVisible(); ).toBeVisible();
await expect(page.getByTestId("model_specsQianfanLLMEndpoint")).toBeVisible(); await expect(page.getByTestId("model_specsQianfanLLMEndpoint")).toBeVisible();
await expect(page.getByTestId("model_specsVertexAI")).toBeVisible(); await expect(page.getByTestId("model_specsVertexAI")).toBeVisible();
@ -168,7 +168,7 @@ test("LLMChain - Filter", async ({ page }) => {
await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible(); await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible();
await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible(); await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible();
await expect( await expect(
page.getByTestId("model_specsAzureChatOpenAI"), page.getByTestId("model_specsAzureChatOpenAI")
).not.toBeVisible(); ).not.toBeVisible();
await expect(page.getByTestId("model_specsChatAnthropic")).not.toBeVisible(); await expect(page.getByTestId("model_specsChatAnthropic")).not.toBeVisible();
await expect(page.getByTestId("model_specsChatLiteLLM")).not.toBeVisible(); await expect(page.getByTestId("model_specsChatLiteLLM")).not.toBeVisible();
@ -178,13 +178,13 @@ test("LLMChain - Filter", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
) )
.click(); .click();
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
) )
.click(); .click();

View file

@ -71,27 +71,32 @@ test("FloatComponent", async ({ page }) => {
await page.getByTestId("showmirostat").click(); await page.getByTestId("showmirostat").click();
expect( expect(
await page.locator('//*[@id="showmirostat"]').isChecked(), await page.locator('//*[@id="showmirostat"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("showmirostat_eta").click(); await page.getByTestId("showmirostat_eta").click();
expect( expect(
await page.locator('//*[@id="showmirostat_eta"]').isChecked(), await page.locator('//*[@id="showmirostat"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("showmirostat_eta").click(); await page.getByTestId("showmirostat_eta").click();
expect( expect(
await page.locator('//*[@id="showmirostat_eta"]').isChecked(), await page.locator('//*[@id="showmirostat_eta"]').isChecked()
).toBeTruthy();
await page.getByTestId("showmirostat_eta").click();
expect(
await page.locator('//*[@id="showmirostat_eta"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByTestId("showmirostat_tau").click(); await page.getByTestId("showmirostat_tau").click();
expect( expect(
await page.locator('//*[@id="showmirostat_tau"]').isChecked(), await page.locator('//*[@id="showmirostat_tau"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("showmirostat_tau").click(); await page.getByTestId("showmirostat_tau").click();
expect( expect(
await page.locator('//*[@id="showmirostat_tau"]').isChecked(), await page.locator('//*[@id="showmirostat_tau"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByTestId("showmodel").click(); await page.getByTestId("showmodel").click();
@ -114,22 +119,22 @@ test("FloatComponent", async ({ page }) => {
await page.getByTestId("shownum_thread").click(); await page.getByTestId("shownum_thread").click();
expect( expect(
await page.locator('//*[@id="shownum_thread"]').isChecked(), await page.locator('//*[@id="shownum_thread"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("shownum_thread").click(); await page.getByTestId("shownum_thread").click();
expect( expect(
await page.locator('//*[@id="shownum_thread"]').isChecked(), await page.locator('//*[@id="shownum_thread"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByTestId("showrepeat_last_n").click(); await page.getByTestId("showrepeat_last_n").click();
expect( expect(
await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), await page.locator('//*[@id="showrepeat_last_n"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("showrepeat_last_n").click(); await page.getByTestId("showrepeat_last_n").click();
expect( expect(
await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), await page.locator('//*[@id="showrepeat_last_n"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
@ -145,7 +150,7 @@ test("FloatComponent", async ({ page }) => {
// showtemperature // showtemperature
await page.locator('//*[@id="showtemperature"]').click(); await page.locator('//*[@id="showtemperature"]').click();
expect( expect(
await page.locator('//*[@id="showtemperature"]').isChecked(), await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();

View file

@ -29,7 +29,7 @@ test("flowSettings", async ({ page }) => {
await page await page
.getByPlaceholder("Flow name") .getByPlaceholder("Flow name")
.fill( .fill(
"Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test", "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test"
); );
await page.getByText("Character limit reached").isVisible(); await page.getByText("Character limit reached").isVisible();
@ -41,7 +41,7 @@ test("flowSettings", async ({ page }) => {
await page await page
.getByPlaceholder("Flow description") .getByPlaceholder("Flow description")
.fill( .fill(
"Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test", "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test"
); );
await page.getByTestId("save-flow-settings").click(); await page.getByTestId("save-flow-settings").click();

View file

@ -60,69 +60,69 @@ test("InputComponent", async ({ page }) => {
expect( expect(
await page await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]') .locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked(), .isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click(); await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(), await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showchroma_server_host"]').click(); await page.locator('//*[@id="showchroma_server_host"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked(), await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showchroma_server_http_port"]').click(); await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(), await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(), await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showcollection_name"]').click(); await page.locator('//*[@id="showcollection_name"]').click();
expect( expect(
await page.locator('//*[@id="showcollection_name"]').isChecked(), await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showindex_directory"]').click(); await page.locator('//*[@id="showindex_directory"]').click();
expect( expect(
await page.locator('//*[@id="showindex_directory"]').isChecked(), await page.locator('//*[@id="showindex_directory"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click(); await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click();
expect( expect(
await page await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]') .locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked(), .isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click(); await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(), await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showchroma_server_host"]').click(); await page.locator('//*[@id="showchroma_server_host"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked(), await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showchroma_server_http_port"]').click(); await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(), await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect( expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(), await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showindex_directory"]').click(); await page.locator('//*[@id="showindex_directory"]').click();
expect( expect(
await page.locator('//*[@id="showindex_directory"]').isChecked(), await page.locator('//*[@id="showindex_directory"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
let valueEditNode = await page let valueEditNode = await page
@ -152,7 +152,7 @@ test("InputComponent", async ({ page }) => {
await page.locator('//*[@id="showcollection_name"]').click(); await page.locator('//*[@id="showcollection_name"]').click();
expect( expect(
await page.locator('//*[@id="showcollection_name"]').isChecked(), await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();

View file

@ -87,77 +87,77 @@ test("IntComponent", async ({ page }) => {
await page.locator('//*[@id="showmodel_kwargs"]').click(); await page.locator('//*[@id="showmodel_kwargs"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showmodel_name"]').click(); await page.locator('//*[@id="showmodel_name"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(), await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showopenai_api_base"]').click(); await page.locator('//*[@id="showopenai_api_base"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(), await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showopenai_api_key"]').click(); await page.locator('//*[@id="showopenai_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(), await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showtemperature"]').click(); await page.locator('//*[@id="showtemperature"]').click();
expect( expect(
await page.locator('//*[@id="showtemperature"]').isChecked(), await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showmodel_kwargs"]').click(); await page.locator('//*[@id="showmodel_kwargs"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showmodel_name"]').click(); await page.locator('//*[@id="showmodel_name"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(), await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showopenai_api_base"]').click(); await page.locator('//*[@id="showopenai_api_base"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(), await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showopenai_api_key"]').click(); await page.locator('//*[@id="showopenai_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(), await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showtemperature"]').click(); await page.locator('//*[@id="showtemperature"]').click();
expect( expect(
await page.locator('//*[@id="showtemperature"]').isChecked(), await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showmodel_kwargs"]').click(); await page.locator('//*[@id="showmodel_kwargs"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showmodel_name"]').click(); await page.locator('//*[@id="showmodel_name"]').click();
expect( expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(), await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showopenai_api_base"]').click(); await page.locator('//*[@id="showopenai_api_base"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(), await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showopenai_api_key"]').click(); await page.locator('//*[@id="showopenai_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(), await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showtemperature"]').click(); await page.locator('//*[@id="showtemperature"]').click();
expect( expect(
await page.locator('//*[@id="showtemperature"]').isChecked(), await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
@ -172,7 +172,7 @@ test("IntComponent", async ({ page }) => {
await page.locator('//*[@id="showtimeout"]').click(); await page.locator('//*[@id="showtimeout"]').click();
expect( expect(
await page.locator('//*[@id="showtimeout"]').isChecked(), await page.locator('//*[@id="showtimeout"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
const valueEditNode = await page const valueEditNode = await page

View file

@ -81,7 +81,7 @@ test("KeypairListComponent", async ({ page }) => {
expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy(); expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy();
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
@ -96,7 +96,7 @@ test("KeypairListComponent", async ({ page }) => {
await page.locator('//*[@id="showcredentials_profile_name"]').click(); await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect( expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showcache"]').click(); await page.locator('//*[@id="showcache"]').click();
expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy(); expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy();

View file

@ -61,7 +61,7 @@ test("LangflowShortcuts", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]', '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]'
) )
.click(); .click();
await page.keyboard.press("Backspace"); await page.keyboard.press("Backspace");
@ -84,7 +84,7 @@ test("LangflowShortcuts", async ({ page }) => {
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]', '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]'
) )
.click(); .click();
await page.keyboard.press("Backspace"); await page.keyboard.press("Backspace");

View file

@ -41,7 +41,7 @@ test("NestedComponent", async ({ page }) => {
await page.locator('//*[@id="showpool_threads"]').click(); await page.locator('//*[@id="showpool_threads"]').click();
expect( expect(
await page.locator('//*[@id="showpool_threads"]').isChecked(), await page.locator('//*[@id="showpool_threads"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
//showtext_key //showtext_key
@ -53,140 +53,140 @@ test("NestedComponent", async ({ page }) => {
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showindex_name // showindex_name
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showindex_name // showindex_name
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showindex_name // showindex_name
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showindex_name // showindex_name
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
// showindex_name // showindex_name
await page.locator('//*[@id="showindex_name"]').click(); await page.locator('//*[@id="showindex_name"]').click();
expect( expect(
await page.locator('//*[@id="showindex_name"]').isChecked(), await page.locator('//*[@id="showindex_name"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// shownamespace // shownamespace
await page.locator('//*[@id="shownamespace"]').click(); await page.locator('//*[@id="shownamespace"]').click();
expect( expect(
await page.locator('//*[@id="shownamespace"]').isChecked(), await page.locator('//*[@id="shownamespace"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
// showpinecone_api_key // showpinecone_api_key
await page.locator('//*[@id="showpinecone_api_key"]').click(); await page.locator('//*[@id="showpinecone_api_key"]').click();
expect( expect(
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
//showpool_threads //showpool_threads
await page.locator('//*[@id="showpool_threads"]').click(); await page.locator('//*[@id="showpool_threads"]').click();
expect( expect(
await page.locator('//*[@id="showpool_threads"]').isChecked(), await page.locator('//*[@id="showpool_threads"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
//showtext_key //showtext_key
await page.locator('//*[@id="showtext_key"]').click(); await page.locator('//*[@id="showtext_key"]').click();
expect( expect(
await page.locator('//*[@id="showtext_key"]').isChecked(), await page.locator('//*[@id="showtext_key"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();

View file

@ -138,7 +138,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.locator('//*[@id="showtemplate"]').click(); await page.locator('//*[@id="showtemplate"]').click();
expect( expect(
await page.locator('//*[@id="showtemplate"]').isChecked(), await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showprompt"]').click(); await page.locator('//*[@id="showprompt"]').click();
@ -158,7 +158,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.locator('//*[@id="showtemplate"]').click(); await page.locator('//*[@id="showtemplate"]').click();
expect( expect(
await page.locator('//*[@id="showtemplate"]').isChecked(), await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showprompt"]').click(); await page.locator('//*[@id="showprompt"]').click();

View file

@ -23,7 +23,7 @@ test("python_api_generation", async ({ page, context }) => {
await page.getByRole("tab", { name: "Python API" }).click(); await page.getByRole("tab", { name: "Python API" }).click();
await page.getByRole("button", { name: "Copy Code" }).click(); await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() => const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText(), navigator.clipboard.readText()
); );
const clipboardContent = await handle.jsonValue(); const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0); expect(clipboardContent.length).toBeGreaterThan(0);

View file

@ -27,7 +27,7 @@ test.describe("save component tests", () => {
// Read your file into a buffer. // Read your file into a buffer.
const jsonContent = readFileSync( const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/flow_group_test.json", "src/frontend/tests/end-to-end/assets/flow_group_test.json",
"utf-8", "utf-8"
); );
// Create the DataTransfer and File // Create the DataTransfer and File
@ -49,7 +49,7 @@ test.describe("save component tests", () => {
"drop", "drop",
{ {
dataTransfer, dataTransfer,
}, }
); );
const genericNoda = page.getByTestId("div-generic-node"); const genericNoda = page.getByTestId("div-generic-node");

View file

@ -262,7 +262,7 @@ test("should share component with share button", async ({ page }) => {
await page.getByText("Set workflow status to public").isVisible(); await page.getByText("Set workflow status to public").isVisible();
await page await page
.getByText( .getByText(
"Attention: API keys in specified fields are automatically removed upon sharing.", "Attention: API keys in specified fields are automatically removed upon sharing."
) )
.isVisible(); .isVisible();
await page.getByText("Export").first().isVisible(); await page.getByText("Export").first().isVisible();

View file

@ -51,7 +51,7 @@ test("TextAreaModalComponent", async ({ page }) => {
await page await page
.getByTestId("textarea-text") .getByTestId("textarea-text")
.fill( .fill(
"test test test test test test test test test test test !@#%*)( 123456789101010101010101111111111 !!!!!!!!!!", "test test test test test test test test test test test !@#%*)( 123456789101010101010101111111111 !!!!!!!!!!"
); );
await page.getByTestId("textarea-text-ExternalLink").click(); await page.getByTestId("textarea-text-ExternalLink").click();

View file

@ -60,7 +60,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Click and hold on the first element // Click and hold on the first element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div'
) )
.hover(); .hover();
await page.mouse.down(); await page.mouse.down();
@ -68,7 +68,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Move to the second element // Move to the second element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[9]/div/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[9]/div/button/div/div'
) )
.hover(); .hover();
@ -92,7 +92,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Click and hold on the first element // Click and hold on the first element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[13]/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[13]/button/div/div'
) )
.hover(); .hover();
await page.mouse.down(); await page.mouse.down();
@ -100,7 +100,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Move to the second element // Move to the second element
await page await page
.locator( .locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div/div', '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div/div'
) )
.hover(); .hover();

View file

@ -45,7 +45,7 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="showload_hidden"]').click(); await page.locator('//*[@id="showload_hidden"]').click();
expect( expect(
await page.locator('//*[@id="showload_hidden"]').isChecked(), await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
@ -81,12 +81,12 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="showload_hidden"]').click(); await page.locator('//*[@id="showload_hidden"]').click();
expect( expect(
await page.locator('//*[@id="showload_hidden"]').isChecked(), await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showmax_concurrency"]').click(); await page.locator('//*[@id="showmax_concurrency"]').click();
expect( expect(
await page.locator('//*[@id="showmax_concurrency"]').isChecked(), await page.locator('//*[@id="showmax_concurrency"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showpath"]').click(); await page.locator('//*[@id="showpath"]').click();
@ -94,22 +94,22 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="showrecursive"]').click(); await page.locator('//*[@id="showrecursive"]').click();
expect( expect(
await page.locator('//*[@id="showrecursive"]').isChecked(), await page.locator('//*[@id="showrecursive"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showsilent_errors"]').click(); await page.locator('//*[@id="showsilent_errors"]').click();
expect( expect(
await page.locator('//*[@id="showsilent_errors"]').isChecked(), await page.locator('//*[@id="showsilent_errors"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showuse_multithreading"]').click(); await page.locator('//*[@id="showuse_multithreading"]').click();
expect( expect(
await page.locator('//*[@id="showuse_multithreading"]').isChecked(), await page.locator('//*[@id="showuse_multithreading"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.locator('//*[@id="showmax_concurrency"]').click(); await page.locator('//*[@id="showmax_concurrency"]').click();
expect( expect(
await page.locator('//*[@id="showmax_concurrency"]').isChecked(), await page.locator('//*[@id="showmax_concurrency"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showpath"]').click(); await page.locator('//*[@id="showpath"]').click();
@ -117,17 +117,17 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="showrecursive"]').click(); await page.locator('//*[@id="showrecursive"]').click();
expect( expect(
await page.locator('//*[@id="showrecursive"]').isChecked(), await page.locator('//*[@id="showrecursive"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showsilent_errors"]').click(); await page.locator('//*[@id="showsilent_errors"]').click();
expect( expect(
await page.locator('//*[@id="showsilent_errors"]').isChecked(), await page.locator('//*[@id="showsilent_errors"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.locator('//*[@id="showuse_multithreading"]').click(); await page.locator('//*[@id="showuse_multithreading"]').click();
expect( expect(
await page.locator('//*[@id="showuse_multithreading"]').isChecked(), await page.locator('//*[@id="showuse_multithreading"]').isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
@ -144,38 +144,38 @@ test("ToggleComponent", async ({ page }) => {
await page.locator('//*[@id="showload_hidden"]').click(); await page.locator('//*[@id="showload_hidden"]').click();
expect( expect(
await page.locator('//*[@id="showload_hidden"]').isChecked(), await page.locator('//*[@id="showload_hidden"]').isChecked()
).toBeTruthy(); ).toBeTruthy();
expect( expect(
await page.getByTestId("toggle-edit-load_hidden").isChecked(), await page.getByTestId("toggle-edit-load_hidden").isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByText("Save Changes", { exact: true }).click(); await page.getByText("Save Changes", { exact: true }).click();
await page.getByTestId("toggle-load_hidden").click(); await page.getByTestId("toggle-load_hidden").click();
expect( expect(
await page.getByTestId("toggle-load_hidden").isChecked(), await page.getByTestId("toggle-load_hidden").isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click(); await page.getByTestId("toggle-load_hidden").click();
expect( expect(
await page.getByTestId("toggle-load_hidden").isChecked(), await page.getByTestId("toggle-load_hidden").isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click(); await page.getByTestId("toggle-load_hidden").click();
expect( expect(
await page.getByTestId("toggle-load_hidden").isChecked(), await page.getByTestId("toggle-load_hidden").isChecked()
).toBeFalsy(); ).toBeFalsy();
await page.getByTestId("toggle-load_hidden").click(); await page.getByTestId("toggle-load_hidden").click();
expect( expect(
await page.getByTestId("toggle-load_hidden").isChecked(), await page.getByTestId("toggle-load_hidden").isChecked()
).toBeTruthy(); ).toBeTruthy();
await page.getByTestId("toggle-load_hidden").click(); await page.getByTestId("toggle-load_hidden").click();
expect( expect(
await page.getByTestId("toggle-load_hidden").isChecked(), await page.getByTestId("toggle-load_hidden").isChecked()
).toBeFalsy(); ).toBeFalsy();
} }
}); });

View file

@ -24,7 +24,7 @@ test("curl_api_generation", async ({ page, context }) => {
await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click(); await page.getByRole("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() => const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText(), navigator.clipboard.readText()
); );
const clipboardContent = await handle.jsonValue(); const clipboardContent = await handle.jsonValue();
const oldValue = clipboardContent; const oldValue = clipboardContent;
@ -50,7 +50,7 @@ test("curl_api_generation", async ({ page, context }) => {
await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("tab", { name: "cURL" }).click();
await page.getByRole("button", { name: "Copy Code" }).click(); await page.getByRole("button", { name: "Copy Code" }).click();
const handle2 = await page.evaluateHandle(() => const handle2 = await page.evaluateHandle(() =>
navigator.clipboard.readText(), navigator.clipboard.readText()
); );
const clipboardContent2 = await handle2.jsonValue(); const clipboardContent2 = await handle2.jsonValue();
const newValue = clipboardContent2; const newValue = clipboardContent2;

View file

@ -4,6 +4,7 @@ from uuid import UUID, uuid4
import pytest import pytest
from fastapi import status from fastapi import status
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from langflow.custom.directory_reader.directory_reader import DirectoryReader from langflow.custom.directory_reader.directory_reader import DirectoryReader
from langflow.services.deps import get_settings_service from langflow.services.deps import get_settings_service