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,
"step": 0.1
},
<<<<<<< HEAD
"data": {
"type": "Prompt",
"node": {
@ -823,8 +822,7 @@
"x": 2969.0261961391298,
"y": 442.1613649809069
},
"dragging": false
=======
"dragging": false,
"load_from_db": false,
"title_case": false
},
@ -907,7 +905,6 @@
]
},
"_type": "CustomComponent"
>>>>>>> origin/dev
},
"description": "Generate embeddings using OpenAI models.",
"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:
raise ValueError(f"Vertex {vertex_id} not found")
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)
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:
self.status = 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
import chromadb
@ -7,6 +8,7 @@ from langchain_core.embeddings import Embeddings
from langchain_core.retrievers import BaseRetriever
from langchain_core.vectorstores import VectorStore
from langflow.base.vectorstores.utils import chroma_collection_to_records
from langflow.custom import CustomComponent
from langflow.schema import Record
@ -48,6 +50,11 @@ class ChromaComponent(CustomComponent):
"display_name": "Server SSL Enabled",
"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(
@ -61,6 +68,7 @@ class ChromaComponent(CustomComponent):
chroma_server_host: Optional[str] = None,
chroma_server_http_port: Optional[int] = None,
chroma_server_grpc_port: Optional[int] = None,
allow_duplicates: bool = False,
) -> Union[VectorStore, BaseRetriever]:
"""
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_http_port (Optional[int]): The HTTP 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:
- Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.
@ -93,32 +102,34 @@ class ChromaComponent(CustomComponent):
)
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
if index_directory is not None:
index_directory = self.resolve_path(index_directory)
chroma = Chroma(
persist_directory=index_directory,
client=client,
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):
documents.append(_input.to_lc_document())
if _input not in _stored_documents_without_id:
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(
persist_directory=index_directory,
client=client,
embedding_function=embedding,
)
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

View file

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

View file

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

View file

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

View file

@ -1 +1 @@
build/*
build/*

View file

@ -82,7 +82,7 @@
"start": "vite",
"build": "vite build",
"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"
},
"simple-git-hooks": {
@ -138,4 +138,4 @@
"ua-parser-js": "^1.0.37",
"vite": "^4.5.2"
}
}
}

View file

@ -28,7 +28,6 @@ export default function SwitchOutputView(nodeId): JSX.Element {
if (resultMessage.raw) {
resultMessage = resultMessage.raw;
}
console.log("resultType", results);
return (
<>
<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 HandleTooltips from "../HandleTooltipComponent";
import OutputComponent from "../OutputComponent";
import OutputModal from "../outputModal";
import { TEXT_FIELD_TYPES } from "./constants";
export default function ParameterComponent({
@ -64,6 +65,7 @@ export default function ParameterComponent({
outputProxy,
}: ParameterComponentType): JSX.Element {
const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
const nodes = useFlowStore((state) => state.nodes);
const edges = useFlowStore((state) => state.edges);
const setNode = useFlowStore((state) => state.setNode);
@ -73,6 +75,17 @@ export default function ParameterComponent({
const updateNodeInternals = useUpdateNodeInternals();
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
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(
data,
name,
@ -80,7 +93,7 @@ export default function ParameterComponent({
handleUpdateValues,
debouncedHandleUpdateValues,
setNode,
setIsLoading,
setIsLoading
);
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
@ -88,7 +101,7 @@ export default function ParameterComponent({
name,
takeSnapshot,
setNode,
updateNodeInternals,
updateNodeInternals
);
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
@ -97,7 +110,7 @@ export default function ParameterComponent({
let disabled =
edges.some(
(edge) =>
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
) ?? false;
const handleRefreshButtonPress = async (name, data) => {
@ -108,7 +121,7 @@ export default function ParameterComponent({
const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[],
skipSnapshot: boolean | undefined = false,
skipSnapshot: boolean | undefined = false
): Promise<void> => {
handleOnNewValueHook(newValue, skipSnapshot);
};
@ -195,14 +208,14 @@ export default function ParameterComponent({
className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background",
!showNode ? "mt-0" : "",
!showNode ? "mt-0" : ""
)}
style={{
borderColor: color ?? nodeColors.unknown,
}}
onClick={() => {
setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!),
groupByFamily(myData, tooltipTitle!, left, nodes!)
);
}}
></Handle>
@ -238,7 +251,40 @@ export default function ParameterComponent({
{renderTitle()}
</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"}>
{required ? "*" : ""}
@ -287,12 +333,12 @@ export default function ParameterComponent({
}
className={classNames(
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 }}
onClick={() => {
setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!),
groupByFamily(myData, tooltipTitle!, left, nodes!)
);
}}
/>
@ -387,7 +433,7 @@ export default function ParameterComponent({
});
}}
name={name}
data={data.node?.template[name]}
data={data.node?.template[name]!}
/>
</div>
{data.node?.template[name]?.refresh_button && (
@ -574,6 +620,13 @@ export default function ParameterComponent({
/>
</div>
</Case>
{openOutputModal && (
<OutputModal
open={openOutputModal}
nodeId={data.id}
setOpen={setOpenOutputModal}
/>
)}
</>
</div>
);

View file

@ -1,47 +1,52 @@
import emojiRegex from "emoji-regex";
import { cloneDeep } from "lodash";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
import IconComponent from "../../components/genericIconComponent";
import InputComponent from "../../components/inputComponent";
import ShadTooltip from "../../components/shadTooltipComponent";
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 Xmark from "../../components/ui/xmark";
import {
RUN_TIMESTAMP_PREFIX,
STATUS_BUILD,
STATUS_BUILDING,
TOOLTIP_OUTDATED_NODE,
} from "../../constants/constants";
import { BuildStatus } from "../../constants/enums";
import { postCustomComponent } from "../../controllers/API";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import useAlertStore from "../../stores/alertStore";
import { useDarkStore } from "../../stores/darkStore";
import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../stores/shortcuts";
import { useTypesStore } from "../../stores/typesStore";
import { APIClassType } from "../../types/api";
import { validationStatusType } from "../../types/components";
import { VertexBuildTypeAPI } from "../../types/api";
import { NodeDataType } from "../../types/flow";
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
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 sortFields from "../utils/sort-fields";
import ParameterComponent from "./components/parameterComponent";
export default function GenericNode({
data,
xPos,
yPos,
selected,
}: {
data: NodeDataType;
selected: boolean;
xPos: number;
yPos: number;
xPos?: number;
yPos?: number;
}): JSX.Element {
const types = useTypesStore((state) => state.types);
const templates = useTypesStore((state) => state.templates);
@ -51,192 +56,47 @@ export default function GenericNode({
const setNode = useFlowStore((state) => state.setNode);
const updateNodeInternals = useUpdateNodeInternals();
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 [nodeName, setNodeName] = useState(data.node!.display_name);
const [inputDescription, setInputDescription] = useState(false);
const [nodeDescription, setNodeDescription] = useState(
data.node?.description!,
data.node?.description!
);
const [isOutdated, setIsOutdated] = useState(false);
const buildStatus = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.status,
(state) => state.flowBuildStatus[data.id]?.status
);
const lastRunTime = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.timestamp,
(state) => state.flowBuildStatus[data.id]?.timestamp
);
const [validationStatus, setValidationStatus] =
useState<validationStatusType | null>(null);
useState<VertexBuildTypeAPI | null>(null);
const [handles, setHandles] = useState<number>(0);
const [validationString, setValidationString] = useState<string>("");
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
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]);
const iconStatus = useIconStatus(buildStatus, validationStatus);
const [showNode, setShowNode] = useState(data.showNode ?? true);
// State for outline color
const isBuilding = useFlowStore((state) => state.isBuilding);
// should be empty string if no duration
// else should be `Duration: ${duration}`
const getDurationString = (duration: number | undefined): string => {
if (duration === undefined) {
return "";
} else {
return `${duration}`;
}
};
const durationString = getDurationString(validationStatus?.data.duration);
const updateNodeCode = useUpdateNodeCode(
data?.id,
data.node!,
setNode,
setIsOutdated,
updateNodeInternals
);
useEffect(() => {
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 name = nodeIconsLucide[data.type] ? data.type : types[data.type];
const nodeIconFragment = (icon) => {
return <span className="text-lg">{icon}</span>;
@ -252,87 +112,24 @@ export default function GenericNode({
);
};
const isDark = useDarkStore((state) => state.dark);
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 (
<>
<IconComponent
name="Play"
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 renderIconStatus = () => {
return (
<div className="generic-node-status-position flex items-center justify-center">
{iconStatus}
</div>
);
};
const getNodeBorderClassName = (
selected: boolean,
showNode: boolean,
buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null,
validationStatus: VertexBuildTypeAPI | null
) => {
const specificClassFromBuildStatus = getSpecificClassFromBuildStatus(
buildStatus,
validationStatus,
isDark
);
const baseBorderClass = getBaseBorderClass(selected);
@ -341,11 +138,13 @@ export default function GenericNode({
baseBorderClass,
nodeSizeClass,
"generic-node-div group/node",
specificClassFromBuildStatus,
specificClassFromBuildStatus
);
return names;
};
// const [openWDoubleCLick, setOpenWDoubleCLick] = useState(false);
const getBaseBorderClass = (selected) => {
let className = selected ? "border border-ring" : "border";
let frozenClass = selected ? "border-ring-frozen" : "border-frozen";
@ -355,10 +154,99 @@ export default function GenericNode({
const getNodeSizeClass = (showNode) =>
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(() => {
return (
<NodeToolbar>
<NodeToolbarComponent
// openWDoubleClick={openWDoubleCLick}
// setOpenWDoubleClick={setOpenWDoubleCLick}
data={data}
deleteNode={(id) => {
takeSnapshot();
@ -375,8 +263,6 @@ export default function GenericNode({
showNode={showNode}
openAdvancedModal={false}
onCloseAdvancedModal={() => {}}
updateNodeCode={updateNodeCode}
isOutdated={isOutdated}
selected={selected}
/>
</NodeToolbar>
@ -392,16 +278,23 @@ export default function GenericNode({
updateNodeCode,
isOutdated,
selected,
shortcuts,
// openWDoubleCLick,
// setOpenWDoubleCLick,
]);
return (
<>
{memoizedNodeToolbarComponent}
<div
// onDoubleClick={(event) => {
// if (!isWrappedWithClass(event, "nodoubleclick"))
// setOpenWDoubleCLick(true);
// }}
className={getNodeBorderClassName(
selected,
showNode,
buildStatus,
validationStatus,
validationStatus
)}
>
{data.node?.beta && showNode && (
@ -470,7 +363,7 @@ export default function GenericNode({
event.preventDefault();
}}
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}
</div>
@ -532,7 +425,7 @@ export default function GenericNode({
}
title={getFieldTitle(
data.node?.template!,
templateField,
templateField
)}
info={data.node?.template[templateField].info}
name={templateField}
@ -560,7 +453,7 @@ export default function GenericNode({
proxy={data.node?.template[templateField].proxy}
showNode={showNode}
/>
),
)
)}
{/* <ParameterComponent
index={0}
@ -592,67 +485,73 @@ export default function GenericNode({
)}
</div>
{showNode && (
<ShadTooltip
content={
buildStatus === BuildStatus.BUILDING ? (
<span> {STATUS_BUILDING} </span>
) : !validationStatus ? (
<span className="flex">{STATUS_BUILD}</span>
) : (
<div className="max-h-100 p-2">
<div>
{lastRunTime && (
<>
<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
content={
buildStatus === BuildStatus.BUILDING ? (
<span> {STATUS_BUILDING} </span>
) : !validationStatus ? (
<span className="flex">{STATUS_BUILD}</span>
) : (
<div className="max-h-100 p-2">
<div>
{lastRunTime && (
<div className="justify-left flex font-normal text-muted-foreground">
<div>{RUN_TIMESTAMP_PREFIX}</div>
<div className="ml-1 text-status-blue">
{lastRunTime}
</div>
</div>
)}
</div>
<div className="justify-left flex font-normal text-muted-foreground">
<div>{RUN_TIMESTAMP_PREFIX}</div>
<div>Duration:</div>
<div className="ml-1 text-status-blue">
{lastRunTime}
{validationStatus?.data.duration}
</div>
</div>
)}
</div>
<div className="justify-left flex font-normal text-muted-foreground">
<div>Duration:</div>
<div className="mb-3 ml-1 text-status-blue">
{validationStatus?.data.duration}
</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>
)
}
side="bottom"
>
<Button
onClick={() => {
if (buildStatus === BuildStatus.BUILDING || isBuilding)
return;
setValidationStatus(null);
buildFlow({ stopNodeId: data.id });
}}
variant="secondary"
className={"group h-9 px-1.5"}
>
<div
data-testid={
`button_run_` + data?.node?.display_name.toLowerCase()
)
}
side="bottom"
>
<div className="generic-node-status-position flex items-center justify-center">
{renderIconStatus(buildStatus, validationStatus)}
</div>
</div>
</Button>
</ShadTooltip>
<Button
onClick={() => {
if (buildStatus === BuildStatus.BUILDING || isBuilding)
return;
setValidationStatus(null);
buildFlow({ stopNodeId: data.id });
}}
variant="secondary"
className={"group h-9 px-1.5"}
>
<div
data-testid={
`button_run_` + data?.node?.display_name.toLowerCase()
}
>
{renderIconStatus()}
</div>
</Button>
</ShadTooltip>
</div>
</>
)}
</div>
</div>
@ -714,12 +613,12 @@ export default function GenericNode({
) : (
<div
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) &&
nameEditable
? "font-light italic"
: "",
: ""
)}
onClick={(e) => {
setInputDescription(true);
@ -781,13 +680,13 @@ export default function GenericNode({
}
title={getFieldTitle(
data.node?.template!,
templateField,
templateField
)}
info={data.node?.template[templateField].info}
name={templateField}
tooltipTitle={
data.node?.template[templateField].input_types?.join(
"\n",
"\n"
) ?? data.node?.template[templateField].type
}
required={data.node!.template[templateField].required}
@ -814,7 +713,7 @@ export default function GenericNode({
<div
className={classNames(
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,
} from "../../constants/constants";
import { useDarkStore } from "../../stores/darkStore";
import { FlowPoolObjectType } from "../../types/chat";
import { VertexBuildTypeAPI } from "../../types/api";
import { NodeType } from "../../types/flow";
import ForwardedIconComponent from "../genericIconComponent";
import TableComponent from "../tableComponent";
@ -19,7 +19,7 @@ function CsvOutputComponent({
flowPool,
}: {
csvNode: NodeType;
flowPool: FlowPoolObjectType;
flowPool: VertexBuildTypeAPI;
}) {
const csvNodeArtifacts = flowPool?.data?.artifacts?.repr;
const jsonString = csvNodeArtifacts?.replace(/'/g, '"');

View file

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

View file

@ -159,6 +159,19 @@ const TableComponent = forwardRef<
}, 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)} />
</div>
);

View file

@ -829,3 +829,9 @@ export const MAX_BATCH_SIZE = 50;
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";
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 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>();
rows.data.forEach((row) => {
sessions.add(row.session_id);
});
return Array.from(sessions);
return { rows: rows.data, columns };
}
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
.results.result ?? "";
console.log(flowPoolNode?.data?.artifacts?.records);
function handleOutputType() {
if (!node) return <>"No node found!"</>;
switch (type) {
@ -252,7 +250,11 @@ export default function IOFieldView({
<div className={left ? "h-56" : "h-full"}>
<RecordsOutputComponent
pagination={!left}
rows={flowPoolNode?.data?.artifacts?.records ?? []}
rows={
flowPoolNode?.data?.artifacts?.map(
(artifact) => artifact.data
) ?? []
}
columnMode="union"
/>
</div>

View file

@ -1,9 +1,7 @@
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";
const fsErrorText =
"Please ensure your file has one of the following extensions:";
const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp";
const useDragAndDrop = (
setIsDragging,
@ -48,14 +46,16 @@ const useDragAndDrop = (
const handleFiles = (files, setFiles, currentFlowId, setErrorData) => {
if (files) {
const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"];
const file = files?.[0];
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");
setErrorData({
title: "Error uploading file",
list: [fsErrorText, snErrorTxt],
list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
});
return;
}

View file

@ -1,11 +1,12 @@
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 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) => {
const setErrorData = useAlertStore((state) => state.setErrorData);
const handleFileChange = async (
@ -14,13 +15,15 @@ export const useHandleFileChange = (setFiles, currentFlowId) => {
const fileInput = event.target;
const file = fileInput.files?.[0];
if (file) {
const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"];
const fileExtension = file.name.split(".").pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(fileExtension)) {
if (
!fileExtension ||
!ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension)
) {
setErrorData({
title: "Error uploading file",
list: [fsErrorText, snErrorTxt],
list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
});
return;
}

View file

@ -1,12 +1,13 @@
import { useEffect } from "react";
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 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 setErrorData = useAlertStore((state) => state.setErrorData);
useEffect(() => {
@ -21,20 +22,15 @@ const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => {
const uid = new ShortUniqueId({ length: 3 });
const blob = items[i].getAsFile();
if (blob) {
const allowedExtensions = [
"png",
"jpg",
"jpeg",
"gif",
"bmp",
"webp",
];
const fileExtension = blob.name.split(".").pop()?.toLowerCase();
if (!fileExtension || !allowedExtensions.includes(fileExtension)) {
if (
!fileExtension ||
!ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension)
) {
setErrorData({
title: "Error uploading file",
list: [fsErrorText, snErrorTxt],
list: [FS_ERROR_TEXT, SN_ERROR_TEXT],
});
return;
}

View file

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

View file

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

View file

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

View file

@ -7,7 +7,6 @@ import IconComponent from "../../../../components/genericIconComponent";
import PaginatorComponent from "../../../../components/paginatorComponent";
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
import { Button } from "../../../../components/ui/button";
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal";
import useAlertStore from "../../../../stores/alertStore";
import { useDarkStore } from "../../../../stores/darkStore";
@ -113,104 +112,6 @@ export default function ComponentsComponent({
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(
selectedFlowsComponentsCards,
addFlow,

View file

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

View file

@ -1,15 +1,6 @@
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
import { Button } from "../../../../../../components/ui/button";
import { cn } from "../../../../../../utils/utils";
type HeaderMessagesComponentProps = {
selectedRows: number[];
handleRemoveMessages: () => void;
};
const HeaderMessagesComponent = ({
selectedRows,
handleRemoveMessages,
}: HeaderMessagesComponentProps) => {
const HeaderMessagesComponent = () => {
return (
<>
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
@ -26,22 +17,6 @@ const HeaderMessagesComponent = ({
behaviors.
</p>
</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>
</>
);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -58,7 +58,7 @@ test("user must interact with chat with Input/Output", async ({ page }) => {
.getByTestId("textarea-input_value")
.nth(1)
.fill(
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!",
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!"
);
await page.getByTestId("icon-LucideSend").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
.getByText(
"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("toggle-edit-return_record").click();
expect(
await page.getByTestId("toggle-edit-return_record").isChecked(),
await page.getByTestId("toggle-edit-return_record").isChecked()
).toBeTruthy();
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(
"src/frontend/tests/end-to-end/assets/chain.png",
"utf-8",
"utf-8"
);
// 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("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText(),
navigator.clipboard.readText()
);
const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0);

View file

@ -27,7 +27,7 @@ test.describe("drag and drop test", () => {
// Read your file into a buffer.
const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/collection.json",
"utf-8",
"utf-8"
);
// Create the DataTransfer and File
@ -47,7 +47,7 @@ test.describe("drag and drop test", () => {
"drop",
{
dataTransfer,
},
}
);
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();
expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(),
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(),
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showendpoint_url"]').click();
expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(),
await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showendpoint_url"]').click();
expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(),
await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showregion_name"]').click();
expect(
await page.locator('//*[@id="showregion_name"]').isChecked(),
await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showregion_name"]').click();
expect(
await page.locator('//*[@id="showregion_name"]').isChecked(),
await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeTruthy();
// showmodel_id
@ -115,7 +115,7 @@ test("dropDownComponent", async ({ page }) => {
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
expect(
await page.locator('//*[@id="showmodel_id"]').isChecked(),
await page.locator('//*[@id="showmodel_id"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showcache"]').click();
@ -126,32 +126,32 @@ test("dropDownComponent", async ({ page }) => {
await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(),
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showcredentials_profile_name"]').click();
expect(
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(),
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showendpoint_url"]').click();
expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(),
await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showendpoint_url"]').click();
expect(
await page.locator('//*[@id="showendpoint_url"]').isChecked(),
await page.locator('//*[@id="showendpoint_url"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showregion_name"]').click();
expect(
await page.locator('//*[@id="showregion_name"]').isChecked(),
await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showregion_name"]').click();
expect(
await page.locator('//*[@id="showregion_name"]').isChecked(),
await page.locator('//*[@id="showregion_name"]').isChecked()
).toBeTruthy();
// showmodel_id
@ -161,7 +161,7 @@ test("dropDownComponent", async ({ page }) => {
// showmodel_id
await page.locator('//*[@id="showmodel_id"]').click();
expect(
await page.locator('//*[@id="showmodel_id"]').isChecked(),
await page.locator('//*[@id="showmodel_id"]').isChecked()
).toBeTruthy();
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
await page
.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();
await page.mouse.down();
@ -72,7 +72,7 @@ test("dropDownComponent", async ({ page }) => {
// Move to the second element
await page
.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();

View file

@ -40,7 +40,7 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page
.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()
.then(async () => {
@ -60,17 +60,17 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page.getByTitle("zoom out").click();
await page
.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()
.then(async () => {
await expect(
page.getByTestId("tooltip-Model Specs").first(),
page.getByTestId("tooltip-Model Specs").first()
).toBeVisible();
await page.waitForTimeout(2000);
await expect(
page.getByTestId("tooltip-Model Specs").first(),
page.getByTestId("tooltip-Model Specs").first()
).toBeVisible();
await page.getByTestId("icon-Search").click();
@ -81,12 +81,12 @@ test("LLMChain - Tooltip", async ({ page }) => {
await page
.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()
.then(async () => {
await expect(
page.getByTestId("empty-tooltip-filter").first(),
page.getByTestId("empty-tooltip-filter").first()
).toBeVisible();
});
});
@ -113,7 +113,7 @@ test("LLMChain - Filter", async ({ page }) => {
await page.waitForTimeout(1000);
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();
@ -136,7 +136,7 @@ test("LLMChain - Filter", async ({ page }) => {
await page
.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();
@ -149,14 +149,14 @@ test("LLMChain - Filter", async ({ page }) => {
await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible();
await expect(page.getByTestId("model_specsChatVertexAI")).toBeVisible();
await expect(
page.getByTestId("model_specsGoogle Generative AI"),
page.getByTestId("model_specsGoogle Generative AI")
).toBeVisible();
await expect(
page.getByTestId("model_specsHugging Face Inference API"),
page.getByTestId("model_specsHugging Face Inference API")
).toBeVisible();
await expect(page.getByTestId("model_specsOllama")).toBeVisible();
await expect(
page.getByTestId("model_specsQianfanChatEndpoint"),
page.getByTestId("model_specsQianfanChatEndpoint")
).toBeVisible();
await expect(page.getByTestId("model_specsQianfanLLMEndpoint")).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("modelsAzure OpenAI")).not.toBeVisible();
await expect(
page.getByTestId("model_specsAzureChatOpenAI"),
page.getByTestId("model_specsAzureChatOpenAI")
).not.toBeVisible();
await expect(page.getByTestId("model_specsChatAnthropic")).not.toBeVisible();
await expect(page.getByTestId("model_specsChatLiteLLM")).not.toBeVisible();
@ -178,13 +178,13 @@ test("LLMChain - Filter", async ({ page }) => {
await page
.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();
await page
.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();

View file

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

View file

@ -29,7 +29,7 @@ test("flowSettings", async ({ page }) => {
await page
.getByPlaceholder("Flow name")
.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();
@ -41,7 +41,7 @@ test("flowSettings", async ({ page }) => {
await page
.getByPlaceholder("Flow description")
.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();

View file

@ -60,69 +60,69 @@ test("InputComponent", async ({ page }) => {
expect(
await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked(),
.isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(),
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_host"]').click();
expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked(),
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(),
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(),
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showcollection_name"]').click();
expect(
await page.locator('//*[@id="showcollection_name"]').isChecked(),
await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showindex_directory"]').click();
expect(
await page.locator('//*[@id="showindex_directory"]').isChecked(),
await page.locator('//*[@id="showindex_directory"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click();
expect(
await page
.locator('//*[@id="showchroma_server_cors_allow_origins"]')
.isChecked(),
.isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_grpc_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(),
await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_host"]').click();
expect(
await page.locator('//*[@id="showchroma_server_host"]').isChecked(),
await page.locator('//*[@id="showchroma_server_host"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_http_port"]').click();
expect(
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(),
await page.locator('//*[@id="showchroma_server_http_port"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click();
expect(
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(),
await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showindex_directory"]').click();
expect(
await page.locator('//*[@id="showindex_directory"]').isChecked(),
await page.locator('//*[@id="showindex_directory"]').isChecked()
).toBeTruthy();
let valueEditNode = await page
@ -152,7 +152,7 @@ test("InputComponent", async ({ page }) => {
await page.locator('//*[@id="showcollection_name"]').click();
expect(
await page.locator('//*[@id="showcollection_name"]').isChecked(),
await page.locator('//*[@id="showcollection_name"]').isChecked()
).toBeTruthy();
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();
expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(),
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmodel_name"]').click();
expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(),
await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showopenai_api_base"]').click();
expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(),
await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showopenai_api_key"]').click();
expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(),
await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showtemperature"]').click();
expect(
await page.locator('//*[@id="showtemperature"]').isChecked(),
await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmodel_kwargs"]').click();
expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(),
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showmodel_name"]').click();
expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(),
await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showopenai_api_base"]').click();
expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(),
await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showopenai_api_key"]').click();
expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(),
await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showtemperature"]').click();
expect(
await page.locator('//*[@id="showtemperature"]').isChecked(),
await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmodel_kwargs"]').click();
expect(
await page.locator('//*[@id="showmodel_kwargs"]').isChecked(),
await page.locator('//*[@id="showmodel_kwargs"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showmodel_name"]').click();
expect(
await page.locator('//*[@id="showmodel_name"]').isChecked(),
await page.locator('//*[@id="showmodel_name"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showopenai_api_base"]').click();
expect(
await page.locator('//*[@id="showopenai_api_base"]').isChecked(),
await page.locator('//*[@id="showopenai_api_base"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showopenai_api_key"]').click();
expect(
await page.locator('//*[@id="showopenai_api_key"]').isChecked(),
await page.locator('//*[@id="showopenai_api_key"]').isChecked()
).toBeFalsy();
await page.locator('//*[@id="showtemperature"]').click();
expect(
await page.locator('//*[@id="showtemperature"]').isChecked(),
await page.locator('//*[@id="showtemperature"]').isChecked()
).toBeFalsy();
await page.getByText("Save Changes", { exact: true }).click();
@ -172,7 +172,7 @@ test("IntComponent", async ({ page }) => {
await page.locator('//*[@id="showtimeout"]').click();
expect(
await page.locator('//*[@id="showtimeout"]').isChecked(),
await page.locator('//*[@id="showtimeout"]').isChecked()
).toBeTruthy();
const valueEditNode = await page

View file

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

View file

@ -61,7 +61,7 @@ test("LangflowShortcuts", async ({ page }) => {
await page
.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();
await page.keyboard.press("Backspace");
@ -84,7 +84,7 @@ test("LangflowShortcuts", async ({ page }) => {
await page
.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();
await page.keyboard.press("Backspace");

View file

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

View file

@ -138,7 +138,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.locator('//*[@id="showtemplate"]').click();
expect(
await page.locator('//*[@id="showtemplate"]').isChecked(),
await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy();
await page.locator('//*[@id="showprompt"]').click();
@ -158,7 +158,7 @@ test("PromptTemplateComponent", async ({ page }) => {
await page.locator('//*[@id="showtemplate"]').click();
expect(
await page.locator('//*[@id="showtemplate"]').isChecked(),
await page.locator('//*[@id="showtemplate"]').isChecked()
).toBeTruthy();
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("button", { name: "Copy Code" }).click();
const handle = await page.evaluateHandle(() =>
navigator.clipboard.readText(),
navigator.clipboard.readText()
);
const clipboardContent = await handle.jsonValue();
expect(clipboardContent.length).toBeGreaterThan(0);

View file

@ -27,7 +27,7 @@ test.describe("save component tests", () => {
// Read your file into a buffer.
const jsonContent = readFileSync(
"src/frontend/tests/end-to-end/assets/flow_group_test.json",
"utf-8",
"utf-8"
);
// Create the DataTransfer and File
@ -49,7 +49,7 @@ test.describe("save component tests", () => {
"drop",
{
dataTransfer,
},
}
);
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(
"Attention: API keys in specified fields are automatically removed upon sharing.",
"Attention: API keys in specified fields are automatically removed upon sharing."
)
.isVisible();
await page.getByText("Export").first().isVisible();

View file

@ -51,7 +51,7 @@ test("TextAreaModalComponent", async ({ page }) => {
await page
.getByTestId("textarea-text")
.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();

View file

@ -60,7 +60,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Click and hold on the first element
await page
.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();
await page.mouse.down();
@ -68,7 +68,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Move to the second element
await page
.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();
@ -92,7 +92,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Click and hold on the first element
await page
.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();
await page.mouse.down();
@ -100,7 +100,7 @@ test("TextInputOutputComponent", async ({ page }) => {
// Move to the second element
await page
.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();

View file

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

View file

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

View file

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