4.8.12 dev (#2928)

* perf: optimize global variables (#2863)

* feat: add global variable types

* add global variables to debug

* fix select dnd

* unify InputTypeConfig params

* feat: http node url support variables (#2891)

* feat: http node url support variables

* change to prompt editor

* fix: global variables (#2892)

* fix global variables

* fix type

* perf: global variables

* perf: workflow delete node error (#2905)

* update lock

* update 4812 doc

* feat: add node course url config (#2897)

* feat: add node course url config

* change plugin course url

* change default doc url

* change url store

* delete unused code

* fix: global variable (#2915)

* fix: global variable

* add comment

* fix: interactive check

* locj

* perf: debug switch to global tab when click run & global var default reset (#2925)

* fix: tool course url

* fix: global var default value & wrap variable form (#2926)

* fix: add dataset tags not update render (#2927)

* feat: tool will save histories

* perf: global variables code

* perf: FE_DOMAIN config

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2024-10-15 20:23:18 +08:00
committed by shilin66
parent 14351d8b8b
commit d6cf5470be
58 changed files with 955 additions and 669 deletions

View File

@@ -81,16 +81,11 @@ const ChatInput = ({
const canSendMessage = havInput && !hasFileUploading;
// Upload files
useRequest2(
async () => {
uploadFiles();
},
{
manual: false,
errorToast: t('common:upload_file_error'),
refreshDeps: [fileList, outLinkAuthData, chatId]
}
);
useRequest2(uploadFiles, {
manual: false,
errorToast: t('common:upload_file_error'),
refreshDeps: [fileList, outLinkAuthData, chatId]
});
/* on send */
const handleSend = useCallback(

View File

@@ -1,7 +1,18 @@
import React from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { Controller, UseFormReturn } from 'react-hook-form';
import { useTranslation } from 'next-i18next';
import { Box, Button, Card, FormControl, Input, Textarea } from '@chakra-ui/react';
import {
Box,
Button,
Card,
Input,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Textarea
} from '@chakra-ui/react';
import ChatAvatar from './ChatAvatar';
import { MessageCardStyle } from '../constants';
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
@@ -10,6 +21,113 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import { ChatBoxInputFormType } from '../type.d';
import { useContextSelector } from 'use-context-selector';
import { ChatBoxContext } from '../Provider';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { useDeepCompareEffect } from 'ahooks';
import { VariableItemType } from '@fastgpt/global/core/app/type';
export const VariableInputItem = ({
item,
variablesForm
}: {
item: VariableItemType;
variablesForm: UseFormReturn<any>;
}) => {
const { register, control, setValue } = variablesForm;
return (
<Box key={item.id} mb={4} pl={1}>
<Box
as={'label'}
display={'flex'}
position={'relative'}
mb={1}
alignItems={'center'}
w={'full'}
>
{item.label}
{item.required && (
<Box
position={'absolute'}
top={'-2px'}
left={'-8px'}
color={'red.500'}
fontWeight={'bold'}
>
*
</Box>
)}
{item.description && <QuestionTip ml={1} label={item.description} />}
</Box>
{item.type === VariableInputEnum.input && (
<Input
maxLength={item.maxLength || 4000}
bg={'myGray.50'}
{...register(item.key, {
required: item.required
})}
/>
)}
{item.type === VariableInputEnum.textarea && (
<Textarea
{...register(item.key, {
required: item.required
})}
rows={5}
bg={'myGray.50'}
maxLength={item.maxLength || 4000}
/>
)}
{item.type === VariableInputEnum.select && (
<Controller
key={item.key}
control={control}
name={item.key}
rules={{ required: item.required }}
render={({ field: { ref, value } }) => {
return (
<MySelect
ref={ref}
width={'100%'}
list={(item.enums || []).map((item: { value: any }) => ({
label: item.value,
value: item.value
}))}
value={value}
onchange={(e) => setValue(item.key, e)}
/>
);
}}
/>
)}
{item.type === VariableInputEnum.numberInput && (
<Controller
key={item.key}
control={control}
name={item.key}
rules={{ required: item.required, min: item.min, max: item.max }}
render={({ field: { ref, value, onChange } }) => (
<NumberInput
step={1}
min={item.min}
max={item.max}
bg={'white'}
rounded={'md'}
clampValueOnBlur={false}
value={value}
onChange={(valueString) => onChange(Number(valueString))}
>
<NumberInputField ref={ref} bg={'white'} />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)}
/>
)}
</Box>
);
};
const VariableInput = ({
chatForm,
@@ -21,13 +139,22 @@ const VariableInput = ({
const { t } = useTranslation();
const { appAvatar, variableList, variablesForm } = useContextSelector(ChatBoxContext, (v) => v);
const { register, setValue, handleSubmit: handleSubmitChat, control } = variablesForm;
const { reset, handleSubmit: handleSubmitChat } = variablesForm;
const defaultValues = useMemo(() => {
return variableList.reduce((acc: Record<string, any>, item) => {
acc[item.key] = item.defaultValue;
return acc;
}, {});
}, [variableList]);
useDeepCompareEffect(() => {
reset(defaultValues);
}, [defaultValues]);
return (
<Box py={3}>
{/* avatar */}
<ChatAvatar src={appAvatar} type={'AI'} />
{/* message */}
<Box textAlign={'left'}>
<Card
order={2}
@@ -38,74 +165,21 @@ const VariableInput = ({
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
>
{variableList.map((item) => (
<Box key={item.id} mb={4}>
<Box as={'label'} display={'inline-block'} position={'relative'} mb={1}>
{item.label}
{item.required && (
<Box
position={'absolute'}
top={'-2px'}
right={'-10px'}
color={'red.500'}
fontWeight={'bold'}
>
*
</Box>
)}
</Box>
{item.type === VariableInputEnum.input && (
<Input
bg={'myWhite.400'}
{...register(item.key, {
required: item.required
})}
/>
)}
{item.type === VariableInputEnum.textarea && (
<Textarea
bg={'myWhite.400'}
{...register(item.key, {
required: item.required
})}
rows={5}
maxLength={4000}
/>
)}
{item.type === VariableInputEnum.select && (
<Controller
key={item.key}
control={control}
name={item.key}
rules={{ required: item.required }}
render={({ field: { ref, value } }) => {
return (
<MySelect
ref={ref}
width={'100%'}
list={(item.enums || []).map((item) => ({
label: item.value,
value: item.value
}))}
value={value}
onchange={(e) => setValue(item.key, e)}
/>
);
}}
/>
)}
</Box>
<VariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
))}
{!chatStarted && (
<Button
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
size={'sm'}
maxW={'100px'}
onClick={handleSubmitChat(() => {
chatForm.setValue('chatStarted', true);
})}
>
{t('common:core.chat.Start Chat')}
</Button>
<Box>
<Button
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
size={'sm'}
maxW={'100px'}
onClick={handleSubmitChat(() => {
chatForm.setValue('chatStarted', true);
})}
>
{t('common:core.chat.Start Chat')}
</Button>
</Box>
)}
</Card>
</Box>

View File

@@ -181,7 +181,7 @@ export const useFileUpload = (props: UseFileUploadOptions) => {
});
// Update file url
copyFile.url = `${location.origin}${previewUrl}`;
copyFile.url = previewUrl;
updateFiles(fileIndex, copyFile);
} catch (error) {
errorFileIndex.push(fileList.findIndex((item) => item.id === file.id)!);

View File

@@ -495,7 +495,8 @@ const ChatBox = (
// 这里,无论是否为交互模式,最后都是 Human 的消息。
const messages = chats2GPTMessages({
messages: newChatList.slice(0, -1),
reserveId: true
reserveId: true,
reserveTool: true
});
const {

View File

@@ -57,9 +57,9 @@ export const checkIsInteractiveByHistories = (chatHistories: ChatSiteItemType[])
) {
const params = lastMessageValue.interactive.params;
// 如果用户选择了,则不认为是交互模式(可能是上一轮以交互结尾,发起的新的一轮对话)
if ('userSelectOptions' in params && 'userSelectedVal' in params) {
if ('userSelectOptions' in params) {
return !params.userSelectedVal;
} else if ('inputForm' in params && 'submitted' in params) {
} else if ('inputForm' in params) {
return !params.submitted;
}
}

View File

@@ -228,7 +228,8 @@ const PluginRunContextProvider = ({
value: []
}
],
reserveId: true
reserveId: true,
reserveTool: true
});
try {