mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
Support simpleApp select workflow (#2772)
* fix: share page id error * feat: simple workflow support childApp tool * perf: aichat box animation
This commit is contained in:
@@ -95,7 +95,7 @@ const AIContentCard = React.memo(function AIContentCard({
|
||||
<AIResponseBox
|
||||
key={key}
|
||||
value={value}
|
||||
isLastChild={isLastChild && i === chatValue.length - 1}
|
||||
isLastResponseValue={isLastChild && i === chatValue.length - 1}
|
||||
isChatting={isChatting}
|
||||
/>
|
||||
);
|
||||
|
@@ -33,7 +33,7 @@ const RenderOutput = () => {
|
||||
<AIResponseBox
|
||||
key={key}
|
||||
value={value}
|
||||
isLastChild={true}
|
||||
isLastResponseValue={true}
|
||||
isChatting={isChatting}
|
||||
/>
|
||||
);
|
||||
|
@@ -110,9 +110,9 @@ const RenderPluginInput = ({
|
||||
*
|
||||
</Box>
|
||||
)}
|
||||
{input.label}
|
||||
{t(input.label as any)}
|
||||
</Box>
|
||||
{input.description && <QuestionTip ml={2} label={input.description} />}
|
||||
{input.description && <QuestionTip ml={2} label={t(input.description as any)} />}
|
||||
</Flex>
|
||||
{render}
|
||||
</Box>
|
||||
|
@@ -24,7 +24,7 @@ import { onSendPrompt } from '../ChatContainer/useChat';
|
||||
|
||||
type props = {
|
||||
value: UserChatItemValueItemType | AIChatItemValueItemType;
|
||||
isLastChild: boolean;
|
||||
isLastResponseValue: boolean;
|
||||
isChatting: boolean;
|
||||
};
|
||||
|
||||
@@ -167,11 +167,13 @@ const RenderInteractive = React.memo(function RenderInteractive({
|
||||
);
|
||||
});
|
||||
|
||||
const AIResponseBox = ({ value, isLastChild, isChatting }: props) => {
|
||||
const AIResponseBox = ({ value, isLastResponseValue, isChatting }: props) => {
|
||||
if (value.type === ChatItemValueTypeEnum.text && value.text)
|
||||
return <RenderText showAnimation={isChatting && isLastChild} text={value.text.content} />;
|
||||
return (
|
||||
<RenderText showAnimation={isChatting && isLastResponseValue} text={value.text.content} />
|
||||
);
|
||||
if (value.type === ChatItemValueTypeEnum.tool && value.tools)
|
||||
return <RenderTool showAnimation={isChatting && isLastChild} tools={value.tools} />;
|
||||
return <RenderTool showAnimation={isChatting} tools={value.tools} />;
|
||||
if (
|
||||
value.type === ChatItemValueTypeEnum.interactive &&
|
||||
value.interactive &&
|
||||
|
@@ -120,6 +120,7 @@ console.log("Chat box loaded")
|
||||
return (
|
||||
<MyModal
|
||||
isOpen
|
||||
isCentered
|
||||
iconSrc="/imgs/modal/usingWay.svg"
|
||||
title={t('common:core.app.outLink.Select Using Way')}
|
||||
onClose={onClose}
|
||||
|
@@ -11,17 +11,10 @@ import {
|
||||
InputGroup,
|
||||
InputLeftElement,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
NumberDecrementStepper,
|
||||
NumberIncrementStepper,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
NumberInputStepper,
|
||||
Switch,
|
||||
Textarea
|
||||
ModalFooter
|
||||
} from '@chakra-ui/react';
|
||||
import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs';
|
||||
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
|
||||
import {
|
||||
FlowNodeTemplateType,
|
||||
@@ -39,14 +32,15 @@ import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { getTeamPlugTemplates } from '@/web/core/app/api/plugin';
|
||||
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { getAppFolderPath } from '@/web/core/app/api/app';
|
||||
import FolderPath from '@/components/common/folder/Path';
|
||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import CostTooltip from '@/components/core/app/plugin/CostTooltip';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import RenderPluginInput from '@/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { AppContext } from '../../context';
|
||||
|
||||
type Props = {
|
||||
selectedTools: FlowNodeTemplateType[];
|
||||
@@ -54,6 +48,13 @@ type Props = {
|
||||
onRemoveTool: (tool: NodeTemplateListItemType) => void;
|
||||
};
|
||||
|
||||
const childAppSystemKey: string[] = [
|
||||
NodeInputKeyEnum.forbidStream,
|
||||
NodeInputKeyEnum.history,
|
||||
NodeInputKeyEnum.historyMaxAmount,
|
||||
NodeInputKeyEnum.userChatInput
|
||||
];
|
||||
|
||||
enum TemplateTypeEnum {
|
||||
'systemPlugin' = 'systemPlugin',
|
||||
'teamPlugin' = 'teamPlugin'
|
||||
@@ -61,6 +62,7 @@ enum TemplateTypeEnum {
|
||||
|
||||
const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) => {
|
||||
const { t } = useTranslation();
|
||||
const { appDetail } = useContextSelector(AppContext, (v) => v);
|
||||
|
||||
const [templateType, setTemplateType] = useState(TemplateTypeEnum.teamPlugin);
|
||||
const [parentId, setParentId] = useState<ParentIdType>('');
|
||||
@@ -85,9 +87,8 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
|
||||
} else if (type === TemplateTypeEnum.teamPlugin) {
|
||||
return getTeamPlugTemplates({
|
||||
parentId,
|
||||
searchKey: searchVal,
|
||||
type: [AppTypeEnum.folder, AppTypeEnum.httpPlugin, AppTypeEnum.plugin]
|
||||
});
|
||||
searchKey: searchVal
|
||||
}).then((res) => res.filter((app) => app.id !== appDetail._id));
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -238,20 +239,24 @@ const RenderList = React.memo(function RenderList({
|
||||
}
|
||||
}, [configTool, reset]);
|
||||
|
||||
const { mutate: onClickAdd, isLoading } = useRequest({
|
||||
mutationFn: async (template: FlowNodeTemplateType) => {
|
||||
const { runAsync: onClickAdd, loading: isLoading } = useRequest2(
|
||||
async (template: NodeTemplateListItemType) => {
|
||||
const res = await getPreviewPluginNode({ appId: template.id });
|
||||
|
||||
// All input is tool params
|
||||
if (res.inputs.every((input) => input.toolDescription)) {
|
||||
if (
|
||||
res.inputs.every((input) => childAppSystemKey.includes(input.key) || input.toolDescription)
|
||||
) {
|
||||
onAddTool(res);
|
||||
} else {
|
||||
reset();
|
||||
setConfigTool(res);
|
||||
}
|
||||
},
|
||||
errorToast: t('common:core.module.templates.Load plugin error')
|
||||
});
|
||||
{
|
||||
errorToast: t('common:core.module.templates.Load plugin error')
|
||||
}
|
||||
);
|
||||
|
||||
return templates.length === 0 && !isLoadingData ? (
|
||||
<EmptyTip text={t('common:core.app.ToolCall.No plugin')} />
|
||||
@@ -340,6 +345,7 @@ const RenderList = React.memo(function RenderList({
|
||||
{!!configTool && (
|
||||
<MyModal
|
||||
isOpen
|
||||
isCentered
|
||||
title={t('common:core.app.ToolCall.Parameter setting')}
|
||||
iconSrc="core/app/toolCall"
|
||||
overflow={'auto'}
|
||||
@@ -359,7 +365,7 @@ const RenderList = React.memo(function RenderList({
|
||||
)}
|
||||
</HStack>
|
||||
{configTool.inputs
|
||||
.filter((item) => !item.toolDescription)
|
||||
.filter((item) => !item.toolDescription && !childAppSystemKey.includes(item.key))
|
||||
.map((input) => {
|
||||
return (
|
||||
<Controller
|
||||
|
@@ -250,7 +250,8 @@ const FieldEditModal = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (isToolInput) {
|
||||
// Focus remove toolDescription
|
||||
if (isToolInput && data.renderTypeList.includes(FlowNodeInputTypeEnum.reference)) {
|
||||
data.toolDescription = data.description;
|
||||
} else {
|
||||
data.toolDescription = undefined;
|
||||
|
@@ -356,17 +356,13 @@ const OutLink = ({
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const { shareId, authToken } = props;
|
||||
const { localUId, setLocalUId } = useShareChatStore();
|
||||
const { localUId, loaded } = useShareChatStore();
|
||||
|
||||
const contextParams = useMemo(() => {
|
||||
if (!localUId) {
|
||||
const localId = `shareChat-${Date.now()}-${nanoid()}`;
|
||||
setLocalUId(localId);
|
||||
return { shareId, outLinkUid: authToken || localId };
|
||||
}
|
||||
|
||||
return { shareId, outLinkUid: authToken || localUId };
|
||||
}, []);
|
||||
}, [authToken, localUId, shareId]);
|
||||
|
||||
if (!loaded || !contextParams.outLinkUid) return <></>;
|
||||
|
||||
return (
|
||||
<ChatContextProvider params={contextParams}>
|
||||
@@ -375,7 +371,7 @@ const Render = (props: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Render;
|
||||
export default React.memo(Render);
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
const shareId = context?.query?.shareId || '';
|
||||
|
@@ -378,7 +378,23 @@ export function form2AppWorkflow(
|
||||
y: 545
|
||||
},
|
||||
version: tool.version,
|
||||
inputs: tool.inputs,
|
||||
inputs: tool.inputs.map((input) => {
|
||||
// Special key value
|
||||
if (input.key === NodeInputKeyEnum.forbidStream) {
|
||||
input.value = true;
|
||||
}
|
||||
// Special tool
|
||||
if (
|
||||
tool.flowNodeType === FlowNodeTypeEnum.appModule &&
|
||||
input.key === NodeInputKeyEnum.history
|
||||
) {
|
||||
return {
|
||||
...input,
|
||||
value: formData.aiSettings.maxHistories
|
||||
};
|
||||
}
|
||||
return input;
|
||||
}),
|
||||
outputs: tool.outputs
|
||||
}
|
||||
],
|
||||
|
@@ -1,25 +1,34 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet(
|
||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ1234567890_',
|
||||
24
|
||||
);
|
||||
|
||||
type State = {
|
||||
localUId: string;
|
||||
setLocalUId: (id: string) => void;
|
||||
loaded: boolean;
|
||||
};
|
||||
|
||||
export const useShareChatStore = create<State>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
localUId: '',
|
||||
setLocalUId(id) {
|
||||
set((state) => {
|
||||
state.localUId = id;
|
||||
});
|
||||
}
|
||||
localUId: `shareChat-${Date.now()}-${nanoid()}`,
|
||||
loaded: false
|
||||
})),
|
||||
{
|
||||
name: 'shareChatStore'
|
||||
name: 'shareChatStore',
|
||||
onRehydrateStorage: () => (state) => {
|
||||
if (state) {
|
||||
state.loaded = true;
|
||||
}
|
||||
},
|
||||
partialize: (state) => ({
|
||||
localUId: state.localUId
|
||||
})
|
||||
}
|
||||
)
|
||||
)
|
||||
|
Reference in New Issue
Block a user