| innerClassName?: string | innerClassName?: string | ||||
| contentClassName?: string | contentClassName?: string | ||||
| footerClassName?: string | footerClassName?: string | ||||
| hideProcessDetail?: boolean | |||||
| } | } | ||||
| export const SimpleBtn = ({ className, isDisabled, onClick, children }: { | export const SimpleBtn = ({ className, isDisabled, onClick, children }: { | ||||
| varList, | varList, | ||||
| innerClassName, | innerClassName, | ||||
| contentClassName, | contentClassName, | ||||
| hideProcessDetail, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const params = useParams() | const params = useParams() | ||||
| <div className={`flex ${contentClassName}`}> | <div className={`flex ${contentClassName}`}> | ||||
| <div className='grow w-0'> | <div className='grow w-0'> | ||||
| {workflowProcessData && ( | {workflowProcessData && ( | ||||
| <WorkflowProcessItem grayBg hideInfo data={workflowProcessData} expand={workflowProcessData.expand} /> | |||||
| <WorkflowProcessItem grayBg hideInfo data={workflowProcessData} expand={workflowProcessData.expand} hideProcessDetail={hideProcessDetail} /> | |||||
| )} | )} | ||||
| {workflowProcessData && !isError && ( | {workflowProcessData && !isError && ( | ||||
| <ResultTab data={workflowProcessData} content={content} /> | <ResultTab data={workflowProcessData} content={content} /> |
| allToolIcons={appMeta?.tool_icons || {}} | allToolIcons={appMeta?.tool_icons || {}} | ||||
| onFeedback={handleFeedback} | onFeedback={handleFeedback} | ||||
| suggestedQuestions={suggestedQuestions} | suggestedQuestions={suggestedQuestions} | ||||
| hideProcessDetail | |||||
| /> | /> | ||||
| ) | ) | ||||
| } | } |
| allToolIcons?: Record<string, string | Emoji> | allToolIcons?: Record<string, string | Emoji> | ||||
| showPromptLog?: boolean | showPromptLog?: boolean | ||||
| chatAnswerContainerInner?: string | chatAnswerContainerInner?: string | ||||
| hideProcessDetail?: boolean | |||||
| } | } | ||||
| const Answer: FC<AnswerProps> = ({ | const Answer: FC<AnswerProps> = ({ | ||||
| item, | item, | ||||
| allToolIcons, | allToolIcons, | ||||
| showPromptLog, | showPromptLog, | ||||
| chatAnswerContainerInner, | chatAnswerContainerInner, | ||||
| hideProcessDetail, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const { | const { | ||||
| } | } | ||||
| { | { | ||||
| workflowProcess && ( | workflowProcess && ( | ||||
| <WorkflowProcess data={workflowProcess} hideInfo /> | |||||
| <WorkflowProcess data={workflowProcess} hideInfo hideProcessDetail={hideProcessDetail} /> | |||||
| ) | ) | ||||
| } | } | ||||
| { | { |
| grayBg?: boolean | grayBg?: boolean | ||||
| expand?: boolean | expand?: boolean | ||||
| hideInfo?: boolean | hideInfo?: boolean | ||||
| hideProcessDetail?: boolean | |||||
| } | } | ||||
| const WorkflowProcessItem = ({ | const WorkflowProcessItem = ({ | ||||
| data, | data, | ||||
| grayBg, | grayBg, | ||||
| expand = false, | expand = false, | ||||
| hideInfo = false, | hideInfo = false, | ||||
| hideProcessDetail = false, | |||||
| }: WorkflowProcessProps) => { | }: WorkflowProcessProps) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [collapse, setCollapse] = useState(!expand) | const [collapse, setCollapse] = useState(!expand) | ||||
| <NodePanel | <NodePanel | ||||
| nodeInfo={node} | nodeInfo={node} | ||||
| hideInfo={hideInfo} | hideInfo={hideInfo} | ||||
| hideProcessDetail={hideProcessDetail} | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| )) | )) |
| chatNode?: ReactNode | chatNode?: ReactNode | ||||
| onFeedback?: (messageId: string, feedback: Feedback) => void | onFeedback?: (messageId: string, feedback: Feedback) => void | ||||
| chatAnswerContainerInner?: string | chatAnswerContainerInner?: string | ||||
| hideProcessDetail?: boolean | |||||
| } | } | ||||
| const Chat: FC<ChatProps> = ({ | const Chat: FC<ChatProps> = ({ | ||||
| config, | config, | ||||
| chatNode, | chatNode, | ||||
| onFeedback, | onFeedback, | ||||
| chatAnswerContainerInner, | chatAnswerContainerInner, | ||||
| hideProcessDetail, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal } = useAppStore(useShallow(state => ({ | const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal } = useAppStore(useShallow(state => ({ | ||||
| allToolIcons={allToolIcons} | allToolIcons={allToolIcons} | ||||
| showPromptLog={showPromptLog} | showPromptLog={showPromptLog} | ||||
| chatAnswerContainerInner={chatAnswerContainerInner} | chatAnswerContainerInner={chatAnswerContainerInner} | ||||
| hideProcessDetail={hideProcessDetail} | |||||
| /> | /> | ||||
| ) | ) | ||||
| } | } |
| taskId={isCallBatchAPI ? ((taskId as number) < 10 ? `0${taskId}` : `${taskId}`) : undefined} | taskId={isCallBatchAPI ? ((taskId as number) < 10 ? `0${taskId}` : `${taskId}`) : undefined} | ||||
| controlClearMoreLikeThis={controlClearMoreLikeThis} | controlClearMoreLikeThis={controlClearMoreLikeThis} | ||||
| isShowTextToSpeech={isShowTextToSpeech} | isShowTextToSpeech={isShowTextToSpeech} | ||||
| hideProcessDetail | |||||
| /> | /> | ||||
| ) | ) | ||||
| <ReactSortable className="space-y-1" | <ReactSortable className="space-y-1" | ||||
| list={payloadWithIds} | list={payloadWithIds} | ||||
| setList={(list) => { | setList={(list) => { | ||||
| if ((payload as PromptItem[])?.[0].role === PromptRole.system && list[0].p.role !== PromptRole.system) | |||||
| if ((payload as PromptItem[])?.[0].role === PromptRole.system && list[0].p?.role !== PromptRole.system) | |||||
| return | return | ||||
| onChange(list.map(item => item.p)) | onChange(list.map(item => item.p)) |
| if (!errorMessages && !payload.memory) { | if (!errorMessages && !payload.memory) { | ||||
| const isChatModel = payload.model.mode === 'chat' | const isChatModel = payload.model.mode === 'chat' | ||||
| const isPromptyEmpty = isChatModel ? !(payload.prompt_template as PromptItem[]).some(t => t.text !== '') : (payload.prompt_template as PromptItem).text === '' | |||||
| const isPromptyEmpty = isChatModel | |||||
| ? !(payload.prompt_template as PromptItem[]).some((t) => { | |||||
| if (t.edition_type === EditionType.jinja2) | |||||
| return t.jinja2_text !== '' | |||||
| return t.text !== '' | |||||
| }) | |||||
| : ((payload.prompt_template as PromptItem).edition_type === EditionType.jinja2 ? (payload.prompt_template as PromptItem).jinja2_text === '' : (payload.prompt_template as PromptItem).text === '') | |||||
| if (isPromptyEmpty) | if (isPromptyEmpty) | ||||
| errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.llm.prompt') }) | errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.llm.prompt') }) | ||||
| } | } |
| 'use client' | 'use client' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| import { useEffect, useState } from 'react' | |||||
| import { useCallback, useEffect, useState } from 'react' | |||||
| import cn from 'classnames' | import cn from 'classnames' | ||||
| import BlockIcon from '../block-icon' | import BlockIcon from '../block-icon' | ||||
| import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' | import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' | ||||
| type Props = { | type Props = { | ||||
| nodeInfo: NodeTracing | nodeInfo: NodeTracing | ||||
| hideInfo?: boolean | hideInfo?: boolean | ||||
| hideProcessDetail?: boolean | |||||
| } | } | ||||
| const NodePanel: FC<Props> = ({ nodeInfo, hideInfo = false }) => { | |||||
| const [collapseState, setCollapseState] = useState<boolean>(true) | |||||
| const NodePanel: FC<Props> = ({ | |||||
| nodeInfo, | |||||
| hideInfo = false, | |||||
| hideProcessDetail, | |||||
| }) => { | |||||
| const [collapseState, doSetCollapseState] = useState<boolean>(true) | |||||
| const setCollapseState = useCallback((state: boolean) => { | |||||
| if (hideProcessDetail) | |||||
| return | |||||
| doSetCollapseState(state) | |||||
| }, [hideProcessDetail]) | |||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const getTime = (time: number) => { | const getTime = (time: number) => { | ||||
| useEffect(() => { | useEffect(() => { | ||||
| setCollapseState(!nodeInfo.expand) | setCollapseState(!nodeInfo.expand) | ||||
| }, [nodeInfo.expand]) | |||||
| }, [nodeInfo.expand, setCollapseState]) | |||||
| return ( | return ( | ||||
| <div className={cn('px-4 py-1', hideInfo && '!p-0')}> | <div className={cn('px-4 py-1', hideInfo && '!p-0')}> | ||||
| )} | )} | ||||
| onClick={() => setCollapseState(!collapseState)} | onClick={() => setCollapseState(!collapseState)} | ||||
| > | > | ||||
| <ChevronRight | |||||
| className={cn( | |||||
| 'shrink-0 w-3 h-3 mr-1 text-gray-400 transition-all group-hover:text-gray-500', | |||||
| !collapseState && 'rotate-90', | |||||
| )} | |||||
| /> | |||||
| {!hideProcessDetail && ( | |||||
| <ChevronRight | |||||
| className={cn( | |||||
| 'shrink-0 w-3 h-3 mr-1 text-gray-400 transition-all group-hover:text-gray-500', | |||||
| !collapseState && 'rotate-90', | |||||
| )} | |||||
| /> | |||||
| )} | |||||
| <BlockIcon size={hideInfo ? 'xs' : 'sm'} className={cn('shrink-0 mr-2', hideInfo && '!mr-1')} type={nodeInfo.node_type} toolIcon={nodeInfo.extras?.icon || nodeInfo.extras} /> | <BlockIcon size={hideInfo ? 'xs' : 'sm'} className={cn('shrink-0 mr-2', hideInfo && '!mr-1')} type={nodeInfo.node_type} toolIcon={nodeInfo.extras?.icon || nodeInfo.extras} /> | ||||
| <div className={cn( | <div className={cn( | ||||
| 'grow text-gray-700 text-[13px] leading-[16px] font-semibold truncate', | 'grow text-gray-700 text-[13px] leading-[16px] font-semibold truncate', | ||||
| )} | )} | ||||
| {nodeInfo.status === 'running' && ( | {nodeInfo.status === 'running' && ( | ||||
| <div className='shrink-0 flex items-center text-primary-600 text-[13px] leading-[16px] font-medium'> | <div className='shrink-0 flex items-center text-primary-600 text-[13px] leading-[16px] font-medium'> | ||||
| <Loading02 className='mr-1 w-3.5 h-3.5 animate-spin' /> | |||||
| <span>Running</span> | |||||
| <span className='mr-2 text-xs font-normal'>Running</span> | |||||
| <Loading02 className='w-3.5 h-3.5 animate-spin' /> | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| {!collapseState && ( | |||||
| {!collapseState && !hideProcessDetail && ( | |||||
| <div className='pb-2'> | <div className='pb-2'> | ||||
| <div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}> | <div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}> | ||||
| {nodeInfo.status === 'stopped' && ( | {nodeInfo.status === 'stopped' && ( |