### What problem does this PR solve? Fix Share-log bugs #3221 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.20.0
| import { Message } from '@/interfaces/database/chat'; | import { Message } from '@/interfaces/database/chat'; | ||||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | import { buildMessageUuidWithRole } from '@/utils/chat'; | ||||
| import { get } from 'lodash'; | import { get } from 'lodash'; | ||||
| import { memo, useCallback } from 'react'; | |||||
| import { memo, useCallback, useMemo } from 'react'; | |||||
| import { useParams } from 'umi'; | import { useParams } from 'umi'; | ||||
| import DebugContent from '../debug-content'; | import DebugContent from '../debug-content'; | ||||
| import { BeginQuery } from '../interface'; | import { BeginQuery } from '../interface'; | ||||
| const { data: canvasInfo } = useFetchAgent(); | const { data: canvasInfo } = useFetchAgent(); | ||||
| const { id: canvasId } = useParams(); | const { id: canvasId } = useParams(); | ||||
| const { uploadCanvasFile, loading } = useUploadCanvasFileWithProgress(); | const { uploadCanvasFile, loading } = useUploadCanvasFileWithProgress(); | ||||
| const getInputs = useCallback((message: Message) => { | const getInputs = useCallback((message: Message) => { | ||||
| return get(message, 'data.inputs', {}) as Record<string, BeginQuery>; | return get(message, 'data.inputs', {}) as Record<string, BeginQuery>; | ||||
| }, []); | }, []); | ||||
| }, | }, | ||||
| [appendUploadResponseList, uploadCanvasFile], | [appendUploadResponseList, uploadCanvasFile], | ||||
| ); | ); | ||||
| const isWaitting = useMemo(() => { | |||||
| const temp = derivedMessages?.some((message, i) => { | |||||
| const flag = | |||||
| message.role === MessageType.Assistant && | |||||
| derivedMessages.length - 1 === i && | |||||
| message.data; | |||||
| return flag; | |||||
| }); | |||||
| return temp; | |||||
| }, [derivedMessages]); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <section className="flex flex-1 flex-col px-5 h-[90vh]"> | <section className="flex flex-1 flex-col px-5 h-[90vh]"> | ||||
| showLikeButton={false} | showLikeButton={false} | ||||
| sendLoading={sendLoading} | sendLoading={sendLoading} | ||||
| > | > | ||||
| <DebugContent | |||||
| parameters={buildInputList(message)} | |||||
| ok={handleOk(message)} | |||||
| isNext={false} | |||||
| btnText={'Submit'} | |||||
| ></DebugContent> | |||||
| {message.role === MessageType.Assistant && | |||||
| derivedMessages.length - 1 === i && ( | |||||
| <DebugContent | |||||
| parameters={buildInputList(message)} | |||||
| message={message} | |||||
| ok={handleOk(message)} | |||||
| isNext={false} | |||||
| btnText={'Submit'} | |||||
| ></DebugContent> | |||||
| )} | |||||
| {message.role === MessageType.Assistant && | |||||
| derivedMessages.length - 1 !== i && ( | |||||
| <div> | |||||
| <div>{message?.data?.tips}</div> | |||||
| <div> | |||||
| {buildInputList(message)?.map((item) => item.value)} | |||||
| </div> | |||||
| </div> | |||||
| )} | |||||
| </MessageItem> | </MessageItem> | ||||
| ); | ); | ||||
| })} | })} | ||||
| <NextMessageInput | <NextMessageInput | ||||
| value={value} | value={value} | ||||
| sendLoading={sendLoading} | sendLoading={sendLoading} | ||||
| disabled={false} | |||||
| sendDisabled={sendLoading} | |||||
| isUploading={loading} | |||||
| disabled={isWaitting} | |||||
| sendDisabled={sendLoading || isWaitting} | |||||
| isUploading={loading || isWaitting} | |||||
| onPressEnter={handlePressEnter} | onPressEnter={handlePressEnter} | ||||
| onInputChange={handleInputChange} | onInputChange={handleInputChange} | ||||
| stopOutputMessage={stopOutputMessage} | stopOutputMessage={stopOutputMessage} |
| import { RAGFlowSelect } from '@/components/ui/select'; | import { RAGFlowSelect } from '@/components/ui/select'; | ||||
| import { Switch } from '@/components/ui/switch'; | import { Switch } from '@/components/ui/switch'; | ||||
| import { Textarea } from '@/components/ui/textarea'; | import { Textarea } from '@/components/ui/textarea'; | ||||
| import { IMessage } from '@/pages/chat/interface'; | |||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import React, { ReactNode, useCallback, useMemo } from 'react'; | import React, { ReactNode, useCallback, useMemo } from 'react'; | ||||
| import { useForm } from 'react-hook-form'; | import { useForm } from 'react-hook-form'; | ||||
| interface IProps { | interface IProps { | ||||
| parameters: BeginQuery[]; | parameters: BeginQuery[]; | ||||
| message?: IMessage; | |||||
| ok(parameters: any[]): void; | ok(parameters: any[]): void; | ||||
| isNext?: boolean; | isNext?: boolean; | ||||
| loading?: boolean; | loading?: boolean; | ||||
| const DebugContent = ({ | const DebugContent = ({ | ||||
| parameters, | parameters, | ||||
| message, | |||||
| ok, | ok, | ||||
| isNext = true, | isNext = true, | ||||
| loading = false, | loading = false, | ||||
| }, | }, | ||||
| [formSchemaValues, ok, parameters], | [formSchemaValues, ok, parameters], | ||||
| ); | ); | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <section> | <section> | ||||
| {message?.data?.tips && <div className="mb-2">{message.data.tips}</div>} | |||||
| <Form {...form}> | <Form {...form}> | ||||
| <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> | <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> | ||||
| {parameters.map((x, idx) => { | {parameters.map((x, idx) => { | ||||
| type="submit" | type="submit" | ||||
| loading={loading} | loading={loading} | ||||
| disabled={!submittable || submitButtonDisabled} | disabled={!submittable || submitButtonDisabled} | ||||
| className="w-full mt-8" | |||||
| className="w-full mt-1" | |||||
| > | > | ||||
| {btnText || t(isNext ? 'common.next' : 'flow.run')} | {btnText || t(isNext ? 'common.next' : 'flow.run')} | ||||
| </ButtonLoading> | </ButtonLoading> |
| AccordionTrigger, | AccordionTrigger, | ||||
| } from '@/components/ui/accordion'; | } from '@/components/ui/accordion'; | ||||
| import { cn } from '@/lib/utils'; | import { cn } from '@/lib/utils'; | ||||
| import { isEmpty } from 'lodash'; | |||||
| import { Operator } from '../constant'; | import { Operator } from '../constant'; | ||||
| import OperatorIcon from '../operator-icon'; | import OperatorIcon from '../operator-icon'; | ||||
| import { | import { | ||||
| toLowerCaseStringAndDeleteChar, | toLowerCaseStringAndDeleteChar, | ||||
| typeMap, | typeMap, | ||||
| } from './workFlowTimeline'; | } from './workFlowTimeline'; | ||||
| const capitalizeWords = (str: string, separator: string = '_'): string => { | |||||
| if (!str) return ''; | |||||
| return str | |||||
| .split(separator) | |||||
| .map((word) => { | |||||
| return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); | |||||
| }) | |||||
| .join(' '); | |||||
| }; | |||||
| const changeToolName = (toolName: any) => { | |||||
| const name = 'Agent ' + capitalizeWords(toolName); | |||||
| return name; | |||||
| }; | |||||
| const ToolTimelineItem = ({ | const ToolTimelineItem = ({ | ||||
| tools, | tools, | ||||
| sendLoading = false, | sendLoading = false, | ||||
| const filteredTools = tools.filter( | const filteredTools = tools.filter( | ||||
| (tool) => !blackList.includes(tool.tool_name), | (tool) => !blackList.includes(tool.tool_name), | ||||
| ); | ); | ||||
| const capitalizeWords = (str: string, separator: string = '_'): string => { | |||||
| if (!str) return ''; | |||||
| return str | |||||
| .split(separator) | |||||
| .map((word) => { | |||||
| return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); | |||||
| }) | |||||
| .join(' '); | |||||
| }; | |||||
| const parentName = (str: string, separator: string = '-->') => { | const parentName = (str: string, separator: string = '-->') => { | ||||
| if (!str) return ''; | if (!str) return ''; | ||||
| const strs = str.split(separator); | const strs = str.split(separator); | ||||
| )} | )} | ||||
| {isShare && ( | {isShare && ( | ||||
| <span> | <span> | ||||
| { | |||||
| typeMap[ | |||||
| toLowerCaseStringAndDeleteChar( | |||||
| tool.tool_name, | |||||
| ) as keyof typeof typeMap | |||||
| ] | |||||
| } | |||||
| {typeMap[ | |||||
| toLowerCaseStringAndDeleteChar( | |||||
| tool.tool_name, | |||||
| ) as keyof typeof typeMap | |||||
| ] ?? changeToolName(tool.tool_name)} | |||||
| </span> | </span> | ||||
| )} | )} | ||||
| <span className="text-text-sub-title text-xs"> | <span className="text-text-sub-title text-xs"> | ||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| </AccordionTrigger> | </AccordionTrigger> | ||||
| <AccordionContent> | |||||
| <div className="space-y-2"> | |||||
| {!isShare && ( | |||||
| {!isShare && ( | |||||
| <AccordionContent> | |||||
| <div className="space-y-2"> | |||||
| <JsonViewer | <JsonViewer | ||||
| data={tool.result} | data={tool.result} | ||||
| title="content" | title="content" | ||||
| ></JsonViewer> | ></JsonViewer> | ||||
| )} | |||||
| {isShare && ( | |||||
| <JsonViewer | |||||
| data={tool.result} | |||||
| title={''} | |||||
| ></JsonViewer> | |||||
| )} | |||||
| </div> | |||||
| </AccordionContent> | |||||
| </div> | |||||
| </AccordionContent> | |||||
| )} | |||||
| {isShare && !isEmpty(tool.arguments) && ( | |||||
| <AccordionContent> | |||||
| <div className="space-y-2"> | |||||
| {tool && | |||||
| tool.arguments && | |||||
| Object.entries(tool.arguments).length && | |||||
| Object.entries(tool.arguments).map(([key, val]) => { | |||||
| return ( | |||||
| <div key={key}> | |||||
| <div className="text-sm font-medium leading-none"> | |||||
| {key} | |||||
| </div> | |||||
| <div className="text-sm text-muted-foreground"> | |||||
| {val || ''} | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| })} | |||||
| </div> | |||||
| </AccordionContent> | |||||
| )} | |||||
| </AccordionItem> | </AccordionItem> | ||||
| </Accordion> | </Accordion> | ||||
| </section> | </section> |
| const handlePageChange = (current?: number, pageSize?: number) => { | const handlePageChange = (current?: number, pageSize?: number) => { | ||||
| console.log('current', current, 'pageSize', pageSize); | console.log('current', current, 'pageSize', pageSize); | ||||
| setPagination((pre) => { | |||||
| return { | |||||
| ...pre, | |||||
| current: current ?? pre.pageSize ? 1 : pre.current, | |||||
| pageSize: pageSize ?? pre.pageSize, | |||||
| }; | |||||
| let page = current || 1; | |||||
| if (pagination.pageSize !== pageSize) { | |||||
| page = 1; | |||||
| } | |||||
| setPagination({ | |||||
| ...pagination, | |||||
| current: page, | |||||
| pageSize: pageSize || 10, | |||||
| }); | }); | ||||
| }; | }; | ||||