diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index b700109b4..c7f344406 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -3,7 +3,6 @@ from typing import Optional from fastapi import ( APIRouter, - Body, Depends, HTTPException, WebSocket, @@ -26,7 +25,6 @@ from langflow.api.v1.schemas import ( VerticesOrderResponse, ) from langflow.graph.graph.base import Graph -from langflow.processing.process import process_tweaks_on_graph from langflow.services.auth.utils import ( get_current_active_user, get_current_user_for_websocket, @@ -318,12 +316,11 @@ async def build_vertex( vertex_id: str, chat_service: "ChatService" = Depends(get_chat_service), current_user=Depends(get_current_active_user), - tweaks: dict = Body(None), - inputs: dict = Body(None), ): """Build a vertex instead of the entire graph.""" start_time = time.perf_counter() try: + start_time = time.perf_counter() cache = chat_service.get_cache(flow_id) if not cache: # If there's no cache @@ -337,10 +334,8 @@ async def build_vertex( graph = cache.get("result") result_dict = {} duration = "" - if tweaks: - graph = process_tweaks_on_graph(graph, tweaks) - if not (vertex := graph.get_vertex(vertex_id)): - raise ValueError(f"Invalid vertex {vertex_id}") + + vertex = graph.get_vertex(vertex_id) try: if not vertex.pinned or not vertex._built: await vertex.build(user_id=current_user.id) @@ -364,7 +359,7 @@ async def build_vertex( raise ValueError(f"No result found for vertex {vertex_id}") chat_service.set_cache(flow_id, graph) except Exception as exc: - params = str(exc) + params = repr(exc) valid = False result_dict = ResultData(results={}) artifacts = {} diff --git a/src/backend/langflow/graph/graph/base.py b/src/backend/langflow/graph/graph/base.py index 370c45461..c52991632 100644 --- a/src/backend/langflow/graph/graph/base.py +++ b/src/backend/langflow/graph/graph/base.py @@ -7,12 +7,8 @@ from langflow.graph.graph.constants import lazy_load_vertex_dict from langflow.graph.graph.utils import process_flow from langflow.graph.schema import InterfaceComponentTypes from langflow.graph.vertex.base import Vertex -from langflow.graph.vertex.types import ( - ChatVertex, - FileToolVertex, - LLMVertex, - ToolkitVertex, -) +from langflow.graph.vertex.types import (ChatVertex, FileToolVertex, LLMVertex, + ToolkitVertex) from langflow.interface.tools.constants import FILE_TOOLS from langflow.utils import payload from loguru import logger @@ -216,7 +212,10 @@ class Graph: def get_vertex(self, vertex_id: str) -> Union[None, Vertex]: """Returns a vertex by id.""" - return self.vertex_map.get(vertex_id) + try: + return self.vertex_map.get(vertex_id) + except KeyError: + raise ValueError(f"Vertex {vertex_id} not found") def get_vertex_edges(self, vertex_id: str) -> List[ContractEdge]: """Returns a list of edges for a given vertex.""" diff --git a/src/backend/langflow/graph/vertex/types.py b/src/backend/langflow/graph/vertex/types.py index 8d23059ce..cb4684d08 100644 --- a/src/backend/langflow/graph/vertex/types.py +++ b/src/backend/langflow/graph/vertex/types.py @@ -2,6 +2,7 @@ import ast import json from typing import Callable, Dict, List, Optional, Union +import yaml from langchain_core.messages import AIMessage from langflow.graph.utils import UnbuiltObject, flatten_list from langflow.graph.vertex.base import StatefulVertex, StatelessVertex @@ -343,8 +344,11 @@ class ChatVertex(StatelessVertex): return str(task.info) else: return f"Task {self.task_id} is not running" - if self.artifacts and "repr" in self.artifacts: - return self.artifacts["repr"] or super()._built_object_repr() + if self.artifacts: + # dump as a yaml string + yaml_str = yaml.dump(self.artifacts, default_flow_style=False) + return yaml_str + return super()._built_object_repr() async def _run(self, *args, **kwargs): if self.is_interface_component: diff --git a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx index cca170067..73331fb27 100644 --- a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx +++ b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx @@ -13,6 +13,8 @@ import FlowSettingsModal from "../../../../modals/flowSettingsModal"; import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; +import { cn } from "../../../../utils/utils"; +import Tooltip from "../../../TooltipComponent"; import IconComponent from "../../../genericIconComponent"; import { Button } from "../../../ui/button"; @@ -26,6 +28,7 @@ export const MenuBar = ({ const setErrorData = useAlertStore((state) => state.setErrorData); const undo = useFlowsManagerStore((state) => state.undo); const redo = useFlowsManagerStore((state) => state.redo); + const saveLoading = useFlowsManagerStore((state) => state.saveLoading); const [openSettings, setOpenSettings] = useState(false); const n = useFlowStore((state) => state.nodes); @@ -112,6 +115,27 @@ export const MenuBar = ({ setOpen={setOpenSettings} > + +
+ + {saveLoading ? "Saving..." : "Saved"} +
+
) : ( <> diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index b9422efab..eeac6d060 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -681,4 +681,4 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([ export const priorityFields = new Set(["code", "template"]); export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]); -export const OUTPUT_TYPES = new Set(["ChatOutput"]); +export const OUTPUT_TYPES = new Set(["ChatOutput",]); diff --git a/src/frontend/src/stores/flowsManagerStore.ts b/src/frontend/src/stores/flowsManagerStore.ts index 4a64b3125..3b4640b21 100644 --- a/src/frontend/src/stores/flowsManagerStore.ts +++ b/src/frontend/src/stores/flowsManagerStore.ts @@ -52,6 +52,7 @@ const useFlowsManagerStore = create((set, get) => ({ }); }, currentFlow: undefined, + saveLoading: false, isLoading: true, setIsLoading: (isLoading: boolean) => set({ isLoading }), refreshFlows: () => { @@ -82,7 +83,7 @@ const useFlowsManagerStore = create((set, get) => ({ if (saveTimeoutId) { clearTimeout(saveTimeoutId); } - + set({ saveLoading: true }); // Set up a new timeout. saveTimeoutId = setTimeout(() => { if (get().currentFlow) { @@ -94,6 +95,7 @@ const useFlowsManagerStore = create((set, get) => ({ }, 300); // Delay of 300ms. }, saveFlow: (flow: FlowType, silent?: boolean) => { + set({ saveLoading: true }) return new Promise((resolve, reject) => { updateFlowInDatabase(flow) .then((updatedFlow) => { @@ -115,6 +117,7 @@ const useFlowsManagerStore = create((set, get) => ({ //update tabs state resolve(); + set({ saveLoading: false }) } }) .catch((err) => { diff --git a/src/frontend/src/stores/storeStore.tsx b/src/frontend/src/stores/storeStore.tsx index 43d16c177..2d519e21a 100644 --- a/src/frontend/src/stores/storeStore.tsx +++ b/src/frontend/src/stores/storeStore.tsx @@ -17,21 +17,3 @@ export const useStoreStore = create((set) => ({ checkHasStore().then((res) => { useStoreStore.setState({ hasStore: res?.enabled ?? false }); }); - -const fetchApiData = async () => { - useStoreStore.setState({ loadingApiKey: true }); - try { - const res = await checkHasApiKey(); - - useStoreStore.setState({ - loadingApiKey: false, - validApiKey: res?.is_valid ?? false, - hasApiKey: res?.has_api_key ?? false, - }); - } catch (e) { - useStoreStore.setState({ loadingApiKey: false }); - console.log(e); - } -}; - -fetchApiData(); diff --git a/src/frontend/src/types/flow/index.ts b/src/frontend/src/types/flow/index.ts index 5f2ed1dc4..127e1a704 100644 --- a/src/frontend/src/types/flow/index.ts +++ b/src/frontend/src/types/flow/index.ts @@ -10,6 +10,8 @@ export type FlowType = { style?: FlowStyleType; is_component?: boolean; last_tested_version?: string; + updated_at?: string; + date_created?: string; parent?: string; }; diff --git a/src/frontend/src/types/zustand/flowsManager/index.ts b/src/frontend/src/types/zustand/flowsManager/index.ts index 2a20c20d8..471d4cf17 100644 --- a/src/frontend/src/types/zustand/flowsManager/index.ts +++ b/src/frontend/src/types/zustand/flowsManager/index.ts @@ -7,6 +7,7 @@ export type FlowsManagerStoreType = { currentFlow: FlowType | undefined; currentFlowId: string; setCurrentFlowId: (currentFlowId: string) => void; + saveLoading: boolean; isLoading: boolean; setIsLoading: (isLoading: boolean) => void; refreshFlows: () => Promise;