"use client"; import { ToolNodeData, UINode, WorkflowToolKey, } from "lib/ai/workflow/workflow.interface"; import { memo, useEffect, useMemo } from "react"; import { InfoIcon, VariableIcon, WrenchIcon } from "lucide-react"; import { useEdges, useNodes, useReactFlow } from "@xyflow/react"; import { appStore } from "@/app/store"; import { WorkflowToolSelect } from "../workflow-tool-select"; import { isString, toAny } from "lib/utils"; import { Separator } from "ui/separator"; import { SelectModel } from "@/components/select-model"; import { OutputSchemaMentionInput } from "../output-schema-mention-input"; import { useWorkflowStore } from "@/app/store/workflow.store"; import { MCPIcon } from "ui/mcp-icon"; import { useTranslations } from "next-intl"; import { Tooltip, TooltipContent, TooltipTrigger } from "ui/tooltip"; import { useMcpList } from "@/hooks/queries/use-mcp-list"; import { exaSearchSchema, exaSearchTool, exaContentsSchema, exaContentsTool, } from "lib/ai/tools/web/web-search"; import { DefaultToolName } from "lib/ai/tools"; export const ToolNodeDataConfig = memo(function ({ data, }: { data: ToolNodeData; }) { const t = useTranslations(); const { updateNodeData } = useReactFlow(); const nodes = useNodes() as UINode[]; const edges = useEdges(); const editable = useWorkflowStore((state) => { return ( state.processIds.length === 0 && state.hasEditAccess && !state.workflow?.isPublished ); }); const { data: mcpList } = useMcpList(); const toolList = useMemo(() => { const mcpTools: WorkflowToolKey[] = (mcpList || []).flatMap((mcp) => { return mcp.toolInfo.map((tool) => { return { type: "mcp-tool", serverId: mcp.id, serverName: mcp.name, id: tool.name, description: tool.description, parameterSchema: tool.inputSchema, }; }); }); const defaultTools: WorkflowToolKey[] = [ { type: "app-tool", id: DefaultToolName.WebSearch, description: exaSearchTool.description!, parameterSchema: exaSearchSchema, }, { type: "app-tool", id: DefaultToolName.WebContent, description: exaContentsTool.description!, parameterSchema: exaContentsSchema, }, ]; return [...mcpTools, ...defaultTools]; }, [mcpList]); useEffect(() => { if (!data.model) { updateNodeData(data.id, { model: appStore.getState().chatModel!, }); } }, []); return (

{t("Common.tool")}

{ updateNodeData(data.id, { tool }); }} tool={data.tool} />

{t("Workflow.descriptionAndSchema")}

{data.tool?.description || Object.keys(data.tool?.parameterSchema?.properties || {}).length > 0 ? (

{data.tool?.description}

{Object.keys(data.tool?.parameterSchema?.properties || {}).length > 0 && (
{Object.keys(data.tool?.parameterSchema?.properties || {}).map( (key) => { const isRequired = data.tool?.parameterSchema?.required?.includes(key); return (
{isRequired && ( * )} {key} {isString(data.tool?.parameterSchema?.properties?.[key]) ? data.tool?.parameterSchema?.properties?.[key] : toAny(data.tool?.parameterSchema?.properties?.[key]) ?.type || "unknown"}
); }, )}
)}
) : (
{t("Workflow.noDescriptionAndSchema")}
)}

Message

{ updateNodeData(data.id, { model, }); }} />
{t("Workflow.toolDescription")}
{ updateNodeData(data.id, { message: content, }); }} />
); }); ToolNodeDataConfig.displayName = "ToolNodeDataConfig"; export const ToolNodeStack = memo(function ({ data }: { data: ToolNodeData }) { const t = useTranslations(); const selectedToolLabel = useMemo(() => { if (!data.tool) return ( <> {t("Common.selectTool")} ); if (data.tool.type == "mcp-tool") { return ( <> {data.tool.serverName}
{data.tool.id}
); } return ( <> {data.tool.id} ); }, [data.tool]); return (
{!data.tool ? (
{t("Common.noResults")}
) : (
{selectedToolLabel}
)}
); }); ToolNodeStack.displayName = "ToolNodeStack";