mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Displays the embedded page of the chat module #3221 Feat: Let the agen operator support the selection of tts model #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
48
web/src/components/embed-container.tsx
Normal file
48
web/src/components/embed-container.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { useFetchAppConf } from '@/hooks/logic-hooks';
|
||||||
|
import { RefreshCcw } from 'lucide-react';
|
||||||
|
import { PropsWithChildren } from 'react';
|
||||||
|
import { RAGFlowAvatar } from './ragflow-avatar';
|
||||||
|
import { Button } from './ui/button';
|
||||||
|
|
||||||
|
type EmbedContainerProps = {
|
||||||
|
title: string;
|
||||||
|
avatar?: string;
|
||||||
|
handleReset?(): void;
|
||||||
|
} & PropsWithChildren;
|
||||||
|
|
||||||
|
export function EmbedContainer({
|
||||||
|
title,
|
||||||
|
avatar,
|
||||||
|
children,
|
||||||
|
handleReset,
|
||||||
|
}: EmbedContainerProps) {
|
||||||
|
const appConf = useFetchAppConf();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="h-[100vh] flex justify-center items-center">
|
||||||
|
<div className="w-40 flex gap-2 absolute left-3 top-12 items-center">
|
||||||
|
<img src="/logo.svg" alt="" />
|
||||||
|
<span className="text-2xl font-bold">{appConf.appName}</span>
|
||||||
|
</div>
|
||||||
|
<div className=" w-[80vw] border rounded-lg">
|
||||||
|
<div className="flex justify-between items-center border-b p-3">
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<RAGFlowAvatar avatar={avatar} name={title} isPerson />
|
||||||
|
<div className="text-xl text-foreground">{title}</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant={'secondary'}
|
||||||
|
className="text-sm text-foreground cursor-pointer"
|
||||||
|
onClick={handleReset}
|
||||||
|
>
|
||||||
|
<div className="flex gap-1 items-center">
|
||||||
|
<RefreshCcw size={14} />
|
||||||
|
<span className="text-lg ">Reset</span>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -23,6 +23,7 @@ import {
|
|||||||
} from '@/constants/common';
|
} from '@/constants/common';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
|
import { Routes } from '@/routes';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useForm, useWatch } from 'react-hook-form';
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
@ -68,7 +69,7 @@ function EmbedDialog({
|
|||||||
|
|
||||||
const generateIframeSrc = useCallback(() => {
|
const generateIframeSrc = useCallback(() => {
|
||||||
const { visibleAvatar, locale } = values;
|
const { visibleAvatar, locale } = values;
|
||||||
let src = `${location.origin}/next-chat/share?shared_id=${token}&from=${from}&auth=${beta}`;
|
let src = `${location.origin}${from === SharedFrom.Agent ? Routes.AgentShare : Routes.ChatShare}?shared_id=${token}&from=${from}&auth=${beta}`;
|
||||||
if (visibleAvatar) {
|
if (visibleAvatar) {
|
||||||
src += '&visible_avatar=1';
|
src += '&visible_avatar=1';
|
||||||
}
|
}
|
||||||
87
web/src/components/embed-dialog/use-show-embed-dialog.ts
Normal file
87
web/src/components/embed-dialog/use-show-embed-dialog.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
||||||
|
import { useFetchManualSystemTokenList } from '@/hooks/user-setting-hooks';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import message from '../ui/message';
|
||||||
|
|
||||||
|
export const useShowTokenEmptyError = () => {
|
||||||
|
const { t } = useTranslate('chat');
|
||||||
|
|
||||||
|
const showTokenEmptyError = useCallback(() => {
|
||||||
|
message.error(t('tokenError'));
|
||||||
|
}, [t]);
|
||||||
|
return { showTokenEmptyError };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useShowBetaEmptyError = () => {
|
||||||
|
const { t } = useTranslate('chat');
|
||||||
|
|
||||||
|
const showBetaEmptyError = useCallback(() => {
|
||||||
|
message.error(t('betaError'));
|
||||||
|
}, [t]);
|
||||||
|
return { showBetaEmptyError };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchTokenListBeforeOtherStep = () => {
|
||||||
|
const { showTokenEmptyError } = useShowTokenEmptyError();
|
||||||
|
const { showBetaEmptyError } = useShowBetaEmptyError();
|
||||||
|
|
||||||
|
const { data: tokenList, fetchSystemTokenList } =
|
||||||
|
useFetchManualSystemTokenList();
|
||||||
|
|
||||||
|
let token = '',
|
||||||
|
beta = '';
|
||||||
|
|
||||||
|
if (Array.isArray(tokenList) && tokenList.length > 0) {
|
||||||
|
token = tokenList[0].token;
|
||||||
|
beta = tokenList[0].beta;
|
||||||
|
}
|
||||||
|
|
||||||
|
token =
|
||||||
|
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
|
||||||
|
|
||||||
|
const handleOperate = useCallback(async () => {
|
||||||
|
const ret = await fetchSystemTokenList();
|
||||||
|
const list = ret;
|
||||||
|
if (Array.isArray(list) && list.length > 0) {
|
||||||
|
if (!list[0].beta) {
|
||||||
|
showBetaEmptyError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return list[0]?.token;
|
||||||
|
} else {
|
||||||
|
showTokenEmptyError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, [fetchSystemTokenList, showBetaEmptyError, showTokenEmptyError]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
token,
|
||||||
|
beta,
|
||||||
|
handleOperate,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useShowEmbedModal = () => {
|
||||||
|
const {
|
||||||
|
visible: embedVisible,
|
||||||
|
hideModal: hideEmbedModal,
|
||||||
|
showModal: showEmbedModal,
|
||||||
|
} = useSetModalState();
|
||||||
|
|
||||||
|
const { handleOperate, token, beta } = useFetchTokenListBeforeOtherStep();
|
||||||
|
|
||||||
|
const handleShowEmbedModal = useCallback(async () => {
|
||||||
|
const succeed = await handleOperate();
|
||||||
|
if (succeed) {
|
||||||
|
showEmbedModal();
|
||||||
|
}
|
||||||
|
}, [handleOperate, showEmbedModal]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
showEmbedModal: handleShowEmbedModal,
|
||||||
|
hideEmbedModal,
|
||||||
|
embedVisible,
|
||||||
|
embedToken: token,
|
||||||
|
beta,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -16,7 +16,7 @@ import { Funnel } from 'lucide-react';
|
|||||||
import { useFormContext, useWatch } from 'react-hook-form';
|
import { useFormContext, useWatch } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { NextLLMSelect } from './llm-select/next';
|
import { NextInnerLLMSelectProps, NextLLMSelect } from './llm-select/next';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
|
|
||||||
const ModelTypes = [
|
const ModelTypes = [
|
||||||
@ -38,7 +38,10 @@ export const LargeModelFilterFormSchema = {
|
|||||||
llm_filter: z.string().optional(),
|
llm_filter: z.string().optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export function LargeModelFormField() {
|
type LargeModelFormFieldProps = Pick<NextInnerLLMSelectProps, 'showTTSModel'>;
|
||||||
|
export function LargeModelFormField({
|
||||||
|
showTTSModel,
|
||||||
|
}: LargeModelFormFieldProps) {
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const filter = useWatch({ control: form.control, name: 'llm_filter' });
|
const filter = useWatch({ control: form.control, name: 'llm_filter' });
|
||||||
@ -85,7 +88,11 @@ export function LargeModelFormField() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<NextLLMSelect {...field} filter={filter} />
|
<NextLLMSelect
|
||||||
|
{...field}
|
||||||
|
filter={filter}
|
||||||
|
showTTSModel={showTTSModel}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +1,41 @@
|
|||||||
import { LlmModelType } from '@/constants/knowledge';
|
import { LlmModelType } from '@/constants/knowledge';
|
||||||
import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
|
import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
|
||||||
import * as SelectPrimitive from '@radix-ui/react-select';
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
||||||
import { forwardRef, memo, useState } from 'react';
|
import { forwardRef, memo, useMemo, useState } from 'react';
|
||||||
import { LlmSettingFieldItems } from '../llm-setting-items/next';
|
import { LlmSettingFieldItems } from '../llm-setting-items/next';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
||||||
import { Select, SelectTrigger, SelectValue } from '../ui/select';
|
import { Select, SelectTrigger, SelectValue } from '../ui/select';
|
||||||
|
|
||||||
interface IProps {
|
export interface NextInnerLLMSelectProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
onInitialValue?: (value: string, option: any) => void;
|
onInitialValue?: (value: string, option: any) => void;
|
||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
filter?: string;
|
filter?: string;
|
||||||
|
showTTSModel?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NextInnerLLMSelect = forwardRef<
|
const NextInnerLLMSelect = forwardRef<
|
||||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||||
IProps
|
NextInnerLLMSelectProps
|
||||||
>(({ value, disabled, filter }, ref) => {
|
>(({ value, disabled, filter, showTTSModel = false }, ref) => {
|
||||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||||
const modelTypes =
|
|
||||||
filter === 'all' || filter === undefined
|
const ttsModel = useMemo(() => {
|
||||||
? [LlmModelType.Chat, LlmModelType.Image2text]
|
return showTTSModel ? [LlmModelType.TTS] : [];
|
||||||
: [filter as LlmModelType];
|
}, [showTTSModel]);
|
||||||
|
|
||||||
|
const modelTypes = useMemo(() => {
|
||||||
|
if (filter === LlmModelType.Chat) {
|
||||||
|
return [LlmModelType.Chat];
|
||||||
|
} else if (filter === LlmModelType.Image2text) {
|
||||||
|
return [LlmModelType.Image2text, ...ttsModel];
|
||||||
|
} else {
|
||||||
|
return [LlmModelType.Chat, LlmModelType.Image2text, ...ttsModel];
|
||||||
|
}
|
||||||
|
}, [filter, ttsModel]);
|
||||||
|
|
||||||
const modelOptions = useComposeLlmOptionsByModelTypes(modelTypes);
|
const modelOptions = useComposeLlmOptionsByModelTypes(modelTypes);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
} from '@/components/file-upload';
|
} from '@/components/file-upload';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { CircleStop, Paperclip, Send, Upload, X } from 'lucide-react';
|
import { CircleStop, Paperclip, Send, Upload, X } from 'lucide-react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
@ -135,7 +136,11 @@ export function NextMessageInput({
|
|||||||
disabled={isUploading || disabled || sendLoading}
|
disabled={isUploading || disabled || sendLoading}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center justify-between gap-1.5">
|
<div
|
||||||
|
className={cn('flex items-center justify-between gap-1.5', {
|
||||||
|
'justify-end': !showUploadIcon,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{showUploadIcon && (
|
{showUploadIcon && (
|
||||||
<FileUploadTrigger asChild>
|
<FileUploadTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import message from '@/components/ui/message';
|
import message from '@/components/ui/message';
|
||||||
import { ChatSearchParams } from '@/constants/chat';
|
import { ChatSearchParams } from '@/constants/chat';
|
||||||
import { IConversation, IDialog } from '@/interfaces/database/chat';
|
import {
|
||||||
|
IConversation,
|
||||||
|
IDialog,
|
||||||
|
IExternalChatInfo,
|
||||||
|
} from '@/interfaces/database/chat';
|
||||||
import { IAskRequestBody } from '@/interfaces/request/chat';
|
import { IAskRequestBody } from '@/interfaces/request/chat';
|
||||||
import { IClientConversation } from '@/pages/next-chats/chat/interface';
|
import { IClientConversation } from '@/pages/next-chats/chat/interface';
|
||||||
import { useGetSharedChatSearchParams } from '@/pages/next-chats/hooks/use-send-shared-message';
|
import { useGetSharedChatSearchParams } from '@/pages/next-chats/hooks/use-send-shared-message';
|
||||||
@ -32,6 +36,7 @@ export const enum ChatApiAction {
|
|||||||
FetchMindMap = 'fetchMindMap',
|
FetchMindMap = 'fetchMindMap',
|
||||||
FetchRelatedQuestions = 'fetchRelatedQuestions',
|
FetchRelatedQuestions = 'fetchRelatedQuestions',
|
||||||
UploadAndParse = 'upload_and_parse',
|
UploadAndParse = 'upload_and_parse',
|
||||||
|
FetchExternalChatInfo = 'fetchExternalChatInfo',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetChatSearchParams = () => {
|
export const useGetChatSearchParams = () => {
|
||||||
@ -418,6 +423,29 @@ export function useUploadAndParseFile() {
|
|||||||
return { data, loading, uploadAndParseFile: mutateAsync };
|
return { data, loading, uploadAndParseFile: mutateAsync };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useFetchExternalChatInfo = () => {
|
||||||
|
const { sharedId: id } = useGetSharedChatSearchParams();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isFetching: loading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery<IExternalChatInfo>({
|
||||||
|
queryKey: [ChatApiAction.FetchExternalChatInfo, id],
|
||||||
|
gcTime: 0,
|
||||||
|
initialData: {} as IExternalChatInfo,
|
||||||
|
enabled: !!id,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await chatService.fetchExternalChatInfo(id!);
|
||||||
|
|
||||||
|
return data?.data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, refetch };
|
||||||
|
};
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region search page
|
//#region search page
|
||||||
|
|||||||
@ -172,3 +172,9 @@ export interface IStats {
|
|||||||
round: [string, number][];
|
round: [string, number][];
|
||||||
thumb_up: [string, number][];
|
thumb_up: [string, number][];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IExternalChatInfo {
|
||||||
|
avatar?: string;
|
||||||
|
title: string;
|
||||||
|
prologue?: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -128,7 +128,7 @@ function AgentForm({ node }: INextOperatorForm) {
|
|||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
<FormContainer>
|
<FormContainer>
|
||||||
{isSubAgent && <DescriptionField></DescriptionField>}
|
{isSubAgent && <DescriptionField></DescriptionField>}
|
||||||
<LargeModelFormField></LargeModelFormField>
|
<LargeModelFormField showTTSModel></LargeModelFormField>
|
||||||
{findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && (
|
{findLlmByUuid(llmId)?.model_type === LlmModelType.Image2text && (
|
||||||
<QueryVariable
|
<QueryVariable
|
||||||
name="visual_files_var"
|
name="visual_files_var"
|
||||||
|
|||||||
65
web/src/pages/agent/hooks/use-send-shared-message.ts
Normal file
65
web/src/pages/agent/hooks/use-send-shared-message.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { SharedFrom } from '@/constants/chat';
|
||||||
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
|
import { IEventList } from '@/hooks/use-send-message';
|
||||||
|
import { useSendAgentMessage } from '@/pages/agent/chat/use-send-agent-message';
|
||||||
|
import trim from 'lodash/trim';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useSearchParams } from 'umi';
|
||||||
|
|
||||||
|
export const useSendButtonDisabled = (value: string) => {
|
||||||
|
return trim(value) === '';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetSharedChatSearchParams = () => {
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const data_prefix = 'data_';
|
||||||
|
const data = Object.fromEntries(
|
||||||
|
searchParams
|
||||||
|
.entries()
|
||||||
|
.filter(([key]) => key.startsWith(data_prefix))
|
||||||
|
.map(([key, value]) => [key.replace(data_prefix, ''), value]),
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
from: searchParams.get('from') as SharedFrom,
|
||||||
|
sharedId: searchParams.get('shared_id'),
|
||||||
|
locale: searchParams.get('locale'),
|
||||||
|
data: data,
|
||||||
|
visibleAvatar: searchParams.get('visible_avatar')
|
||||||
|
? searchParams.get('visible_avatar') !== '1'
|
||||||
|
: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSendNextSharedMessage = (
|
||||||
|
addEventList: (data: IEventList, messageId: string) => void,
|
||||||
|
) => {
|
||||||
|
const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
|
||||||
|
const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`;
|
||||||
|
|
||||||
|
const [params, setParams] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
visible: parameterDialogVisible,
|
||||||
|
hideModal: hideParameterDialog,
|
||||||
|
showModal: showParameterDialog,
|
||||||
|
} = useSetModalState();
|
||||||
|
|
||||||
|
const ret = useSendAgentMessage(url, addEventList, params);
|
||||||
|
|
||||||
|
const ok = useCallback(
|
||||||
|
(params: any[]) => {
|
||||||
|
setParams(params);
|
||||||
|
hideParameterDialog();
|
||||||
|
},
|
||||||
|
[hideParameterDialog],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...ret,
|
||||||
|
hasError: false,
|
||||||
|
parameterDialogVisible,
|
||||||
|
hideParameterDialog,
|
||||||
|
showParameterDialog,
|
||||||
|
ok,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,18 +1,13 @@
|
|||||||
|
import { useFetchTokenListBeforeOtherStep } from '@/components/embed-dialog/use-show-embed-dialog';
|
||||||
import { SharedFrom } from '@/constants/chat';
|
import { SharedFrom } from '@/constants/chat';
|
||||||
import {
|
import { useShowDeleteConfirm } from '@/hooks/common-hooks';
|
||||||
useSetModalState,
|
|
||||||
useShowDeleteConfirm,
|
|
||||||
useTranslate,
|
|
||||||
} from '@/hooks/common-hooks';
|
|
||||||
import {
|
import {
|
||||||
useCreateSystemToken,
|
useCreateSystemToken,
|
||||||
useFetchManualSystemTokenList,
|
|
||||||
useFetchSystemTokenList,
|
useFetchSystemTokenList,
|
||||||
useRemoveSystemToken,
|
useRemoveSystemToken,
|
||||||
} from '@/hooks/user-setting-hooks';
|
} from '@/hooks/user-setting-hooks';
|
||||||
import { IStats } from '@/interfaces/database/chat';
|
import { IStats } from '@/interfaces/database/chat';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { message } from 'antd';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
export const useOperateApiKey = (idKey: string, dialogId?: string) => {
|
export const useOperateApiKey = (idKey: string, dialogId?: string) => {
|
||||||
@ -62,94 +57,11 @@ export const useSelectChartStatsList = (): ChartStatsType => {
|
|||||||
}, {} as ChartStatsType);
|
}, {} as ChartStatsType);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useShowTokenEmptyError = () => {
|
|
||||||
const { t } = useTranslate('chat');
|
|
||||||
|
|
||||||
const showTokenEmptyError = useCallback(() => {
|
|
||||||
message.error(t('tokenError'));
|
|
||||||
}, [t]);
|
|
||||||
return { showTokenEmptyError };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useShowBetaEmptyError = () => {
|
|
||||||
const { t } = useTranslate('chat');
|
|
||||||
|
|
||||||
const showBetaEmptyError = useCallback(() => {
|
|
||||||
message.error(t('betaError'));
|
|
||||||
}, [t]);
|
|
||||||
return { showBetaEmptyError };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getUrlWithToken = (token: string, from: string = 'chat') => {
|
const getUrlWithToken = (token: string, from: string = 'chat') => {
|
||||||
const { protocol, host } = window.location;
|
const { protocol, host } = window.location;
|
||||||
return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
|
return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFetchTokenListBeforeOtherStep = () => {
|
|
||||||
const { showTokenEmptyError } = useShowTokenEmptyError();
|
|
||||||
const { showBetaEmptyError } = useShowBetaEmptyError();
|
|
||||||
|
|
||||||
const { data: tokenList, fetchSystemTokenList } =
|
|
||||||
useFetchManualSystemTokenList();
|
|
||||||
|
|
||||||
let token = '',
|
|
||||||
beta = '';
|
|
||||||
|
|
||||||
if (Array.isArray(tokenList) && tokenList.length > 0) {
|
|
||||||
token = tokenList[0].token;
|
|
||||||
beta = tokenList[0].beta;
|
|
||||||
}
|
|
||||||
|
|
||||||
token =
|
|
||||||
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
|
|
||||||
|
|
||||||
const handleOperate = useCallback(async () => {
|
|
||||||
const ret = await fetchSystemTokenList();
|
|
||||||
const list = ret;
|
|
||||||
if (Array.isArray(list) && list.length > 0) {
|
|
||||||
if (!list[0].beta) {
|
|
||||||
showBetaEmptyError();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return list[0]?.token;
|
|
||||||
} else {
|
|
||||||
showTokenEmptyError();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}, [fetchSystemTokenList, showBetaEmptyError, showTokenEmptyError]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
token,
|
|
||||||
beta,
|
|
||||||
handleOperate,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useShowEmbedModal = () => {
|
|
||||||
const {
|
|
||||||
visible: embedVisible,
|
|
||||||
hideModal: hideEmbedModal,
|
|
||||||
showModal: showEmbedModal,
|
|
||||||
} = useSetModalState();
|
|
||||||
|
|
||||||
const { handleOperate, token, beta } = useFetchTokenListBeforeOtherStep();
|
|
||||||
|
|
||||||
const handleShowEmbedModal = useCallback(async () => {
|
|
||||||
const succeed = await handleOperate();
|
|
||||||
if (succeed) {
|
|
||||||
showEmbedModal();
|
|
||||||
}
|
|
||||||
}, [handleOperate, showEmbedModal]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
showEmbedModal: handleShowEmbedModal,
|
|
||||||
hideEmbedModal,
|
|
||||||
embedVisible,
|
|
||||||
embedToken: token,
|
|
||||||
beta,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const usePreviewChat = (idKey: string) => {
|
export const usePreviewChat = (idKey: string) => {
|
||||||
const { handleOperate } = useFetchTokenListBeforeOtherStep();
|
const { handleOperate } = useFetchTokenListBeforeOtherStep();
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import EmbedDialog from '@/components/embed-dialog';
|
||||||
|
import { useShowEmbedModal } from '@/components/embed-dialog/use-show-embed-dialog';
|
||||||
import { PageHeader } from '@/components/page-header';
|
import { PageHeader } from '@/components/page-header';
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
@ -35,7 +37,6 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { useParams } from 'umi';
|
import { useParams } from 'umi';
|
||||||
import AgentCanvas from './canvas';
|
import AgentCanvas from './canvas';
|
||||||
import { DropdownProvider } from './canvas/context';
|
import { DropdownProvider } from './canvas/context';
|
||||||
import EmbedDialog from './embed-dialog';
|
|
||||||
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
|
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
|
||||||
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
||||||
import { useGetBeginNodeDataInputs } from './hooks/use-get-begin-query';
|
import { useGetBeginNodeDataInputs } from './hooks/use-get-begin-query';
|
||||||
@ -44,7 +45,6 @@ import {
|
|||||||
useSaveGraphBeforeOpeningDebugDrawer,
|
useSaveGraphBeforeOpeningDebugDrawer,
|
||||||
useWatchAgentChange,
|
useWatchAgentChange,
|
||||||
} from './hooks/use-save-graph';
|
} from './hooks/use-save-graph';
|
||||||
import { useShowEmbedModal } from './hooks/use-show-dialog';
|
|
||||||
import { SettingDialog } from './setting-dialog';
|
import { SettingDialog } from './setting-dialog';
|
||||||
import { UploadAgentDialog } from './upload-agent-dialog';
|
import { UploadAgentDialog } from './upload-agent-dialog';
|
||||||
import { useAgentHistoryManager } from './use-agent-history-manager';
|
import { useAgentHistoryManager } from './use-agent-history-manager';
|
||||||
|
|||||||
233
web/src/pages/agent/share/index.tsx
Normal file
233
web/src/pages/agent/share/index.tsx
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
import { EmbedContainer } from '@/components/embed-container';
|
||||||
|
import { FileUploadProps } from '@/components/file-upload';
|
||||||
|
import { NextMessageInput } from '@/components/message-input/next';
|
||||||
|
import MessageItem from '@/components/next-message-item';
|
||||||
|
import PdfDrawer from '@/components/pdf-drawer';
|
||||||
|
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
||||||
|
import { MessageType } from '@/constants/chat';
|
||||||
|
import {
|
||||||
|
useFetchExternalAgentInputs,
|
||||||
|
useUploadCanvasFileWithProgress,
|
||||||
|
} from '@/hooks/use-agent-request';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import i18n from '@/locales/config';
|
||||||
|
import DebugContent from '@/pages/agent/debug-content';
|
||||||
|
import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log';
|
||||||
|
import { useAwaitCompentData } from '@/pages/agent/hooks/use-chat-logic';
|
||||||
|
import { IInputs } from '@/pages/agent/interface';
|
||||||
|
import { useSendButtonDisabled } from '@/pages/chat/hooks';
|
||||||
|
import { buildMessageUuidWithRole } from '@/utils/chat';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import React, { forwardRef, useCallback, useState } from 'react';
|
||||||
|
import {
|
||||||
|
useGetSharedChatSearchParams,
|
||||||
|
useSendNextSharedMessage,
|
||||||
|
} from '../hooks/use-send-shared-message';
|
||||||
|
import { ParameterDialog } from './parameter-dialog';
|
||||||
|
|
||||||
|
const ChatContainer = () => {
|
||||||
|
const {
|
||||||
|
sharedId: conversationId,
|
||||||
|
locale,
|
||||||
|
visibleAvatar,
|
||||||
|
} = useGetSharedChatSearchParams();
|
||||||
|
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||||
|
useClickDrawer();
|
||||||
|
|
||||||
|
const { uploadCanvasFile, loading } =
|
||||||
|
useUploadCanvasFileWithProgress(conversationId);
|
||||||
|
const {
|
||||||
|
addEventList,
|
||||||
|
setCurrentMessageId,
|
||||||
|
currentEventListWithoutMessageById,
|
||||||
|
clearEventList,
|
||||||
|
} = useCacheChatLog();
|
||||||
|
const {
|
||||||
|
handlePressEnter,
|
||||||
|
handleInputChange,
|
||||||
|
value,
|
||||||
|
sendLoading,
|
||||||
|
scrollRef,
|
||||||
|
messageContainerRef,
|
||||||
|
derivedMessages,
|
||||||
|
hasError,
|
||||||
|
stopOutputMessage,
|
||||||
|
findReferenceByMessageId,
|
||||||
|
appendUploadResponseList,
|
||||||
|
parameterDialogVisible,
|
||||||
|
showParameterDialog,
|
||||||
|
sendFormMessage,
|
||||||
|
addNewestOneAnswer,
|
||||||
|
ok,
|
||||||
|
resetSession,
|
||||||
|
} = useSendNextSharedMessage(addEventList);
|
||||||
|
const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
|
||||||
|
derivedMessages,
|
||||||
|
sendFormMessage,
|
||||||
|
canvasId: conversationId as string,
|
||||||
|
});
|
||||||
|
const sendDisabled = useSendButtonDisabled(value);
|
||||||
|
const { data: inputsData } = useFetchExternalAgentInputs();
|
||||||
|
const [agentInfo, setAgentInfo] = useState<IInputs>({
|
||||||
|
avatar: '',
|
||||||
|
title: '',
|
||||||
|
inputs: {},
|
||||||
|
prologue: '',
|
||||||
|
});
|
||||||
|
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
|
||||||
|
useCallback(
|
||||||
|
async (files, options) => {
|
||||||
|
const ret = await uploadCanvasFile({ files, options });
|
||||||
|
appendUploadResponseList(ret.data, files);
|
||||||
|
},
|
||||||
|
[appendUploadResponseList, uploadCanvasFile],
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (locale && i18n.language !== locale) {
|
||||||
|
i18n.changeLanguage(locale);
|
||||||
|
}
|
||||||
|
}, [locale, visibleAvatar]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const { avatar, title, inputs } = inputsData;
|
||||||
|
setAgentInfo({
|
||||||
|
avatar,
|
||||||
|
title,
|
||||||
|
inputs: inputs,
|
||||||
|
prologue: '',
|
||||||
|
});
|
||||||
|
}, [inputsData, setAgentInfo]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (inputsData.prologue) {
|
||||||
|
addNewestOneAnswer({
|
||||||
|
answer: inputsData.prologue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [inputsData.prologue, addNewestOneAnswer]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) {
|
||||||
|
showParameterDialog();
|
||||||
|
}
|
||||||
|
}, [inputsData, showParameterDialog]);
|
||||||
|
|
||||||
|
const handleInputsModalOk = (params: any[]) => {
|
||||||
|
ok(params);
|
||||||
|
};
|
||||||
|
const handleReset = () => {
|
||||||
|
resetSession();
|
||||||
|
clearEventList();
|
||||||
|
};
|
||||||
|
if (!conversationId) {
|
||||||
|
return <div>empty</div>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EmbedContainer
|
||||||
|
title={agentInfo.title}
|
||||||
|
avatar={agentInfo.avatar}
|
||||||
|
handleReset={handleReset}
|
||||||
|
>
|
||||||
|
<div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3">
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'flex flex-1 flex-col overflow-auto scrollbar-auto m-auto w-5/6',
|
||||||
|
)}
|
||||||
|
ref={messageContainerRef}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{derivedMessages?.map((message, i) => {
|
||||||
|
return (
|
||||||
|
<MessageItem
|
||||||
|
visibleAvatar={visibleAvatar}
|
||||||
|
conversationId={conversationId}
|
||||||
|
currentEventListWithoutMessageById={
|
||||||
|
currentEventListWithoutMessageById
|
||||||
|
}
|
||||||
|
setCurrentMessageId={setCurrentMessageId}
|
||||||
|
key={buildMessageUuidWithRole(message)}
|
||||||
|
item={message}
|
||||||
|
nickname="You"
|
||||||
|
reference={findReferenceByMessageId(message.id)}
|
||||||
|
loading={
|
||||||
|
message.role === MessageType.Assistant &&
|
||||||
|
sendLoading &&
|
||||||
|
derivedMessages?.length - 1 === i
|
||||||
|
}
|
||||||
|
isShare={true}
|
||||||
|
avatarDialog={agentInfo.avatar}
|
||||||
|
agentName={agentInfo.title}
|
||||||
|
index={i}
|
||||||
|
clickDocumentButton={clickDocumentButton}
|
||||||
|
showLikeButton={false}
|
||||||
|
showLoudspeaker={false}
|
||||||
|
showLog={false}
|
||||||
|
sendLoading={sendLoading}
|
||||||
|
>
|
||||||
|
{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>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div ref={scrollRef} />
|
||||||
|
</div>
|
||||||
|
<div className="flex w-full justify-center mb-8">
|
||||||
|
<div className="w-5/6">
|
||||||
|
<NextMessageInput
|
||||||
|
isShared
|
||||||
|
value={value}
|
||||||
|
disabled={hasError || isWaitting}
|
||||||
|
sendDisabled={sendDisabled || isWaitting}
|
||||||
|
conversationId={conversationId}
|
||||||
|
onInputChange={handleInputChange}
|
||||||
|
onPressEnter={handlePressEnter}
|
||||||
|
sendLoading={sendLoading}
|
||||||
|
stopOutputMessage={stopOutputMessage}
|
||||||
|
onUpload={handleUploadFile}
|
||||||
|
isUploading={loading || isWaitting}
|
||||||
|
></NextMessageInput>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</EmbedContainer>
|
||||||
|
{visible && (
|
||||||
|
<PdfDrawer
|
||||||
|
visible={visible}
|
||||||
|
hideModal={hideModal}
|
||||||
|
documentId={documentId}
|
||||||
|
chunk={selectedChunk}
|
||||||
|
></PdfDrawer>
|
||||||
|
)}
|
||||||
|
{parameterDialogVisible && (
|
||||||
|
<ParameterDialog
|
||||||
|
// hideModal={hideParameterDialog}
|
||||||
|
ok={handleInputsModalOk}
|
||||||
|
data={agentInfo.inputs}
|
||||||
|
></ParameterDialog>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default forwardRef(ChatContainer);
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import EmbedDialog from '@/components/embed-dialog';
|
||||||
|
import { useShowEmbedModal } from '@/components/embed-dialog/use-show-embed-dialog';
|
||||||
import { PageHeader } from '@/components/page-header';
|
import { PageHeader } from '@/components/page-header';
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
@ -9,6 +11,7 @@ import {
|
|||||||
} from '@/components/ui/breadcrumb';
|
} from '@/components/ui/breadcrumb';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { SharedFrom } from '@/constants/chat';
|
||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import {
|
import {
|
||||||
@ -20,6 +23,7 @@ import { cn } from '@/lib/utils';
|
|||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { ArrowUpRight, LogOut, Send } from 'lucide-react';
|
import { ArrowUpRight, LogOut, Send } from 'lucide-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useParams } from 'umi';
|
||||||
import { useHandleClickConversationCard } from '../hooks/use-click-card';
|
import { useHandleClickConversationCard } from '../hooks/use-click-card';
|
||||||
import { ChatSettings } from './app-settings/chat-settings';
|
import { ChatSettings } from './app-settings/chat-settings';
|
||||||
import { MultipleChatBox } from './chat-box/multiple-chat-box';
|
import { MultipleChatBox } from './chat-box/multiple-chat-box';
|
||||||
@ -29,6 +33,7 @@ import { useAddChatBox } from './use-add-box';
|
|||||||
import { useSwitchDebugMode } from './use-switch-debug-mode';
|
import { useSwitchDebugMode } from './use-switch-debug-mode';
|
||||||
|
|
||||||
export default function Chat() {
|
export default function Chat() {
|
||||||
|
const { id } = useParams();
|
||||||
const { navigateToChatList } = useNavigatePage();
|
const { navigateToChatList } = useNavigatePage();
|
||||||
const { data } = useFetchDialog();
|
const { data } = useFetchDialog();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -46,6 +51,9 @@ export default function Chat() {
|
|||||||
hasThreeChatBox,
|
hasThreeChatBox,
|
||||||
} = useAddChatBox();
|
} = useAddChatBox();
|
||||||
|
|
||||||
|
const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
|
||||||
|
useShowEmbedModal();
|
||||||
|
|
||||||
const { conversationId, isNew } = useGetChatSearchParams();
|
const { conversationId, isNew } = useGetChatSearchParams();
|
||||||
|
|
||||||
const { isDebugMode, switchDebugMode } = useSwitchDebugMode();
|
const { isDebugMode, switchDebugMode } = useSwitchDebugMode();
|
||||||
@ -87,7 +95,7 @@ export default function Chat() {
|
|||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
</BreadcrumbList>
|
</BreadcrumbList>
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
<Button>
|
<Button onClick={showEmbedModal}>
|
||||||
<Send />
|
<Send />
|
||||||
{t('common.embedIntoSite')}
|
{t('common.embedIntoSite')}
|
||||||
</Button>
|
</Button>
|
||||||
@ -133,6 +141,16 @@ export default function Chat() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
{embedVisible && (
|
||||||
|
<EmbedDialog
|
||||||
|
visible={embedVisible}
|
||||||
|
hideModal={hideEmbedModal}
|
||||||
|
token={id!}
|
||||||
|
from={SharedFrom.Chat}
|
||||||
|
beta={beta}
|
||||||
|
isAgent={false}
|
||||||
|
></EmbedDialog>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,20 @@
|
|||||||
import { SharedFrom } from '@/constants/chat';
|
import { MessageType, SharedFrom } from '@/constants/chat';
|
||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useCreateNextSharedConversation } from '@/hooks/chat-hooks';
|
||||||
import { IEventList } from '@/hooks/use-send-message';
|
import {
|
||||||
import { useSendAgentMessage } from '@/pages/agent/chat/use-send-agent-message';
|
useHandleMessageInputChange,
|
||||||
|
useSelectDerivedMessages,
|
||||||
|
useSendMessageWithSse,
|
||||||
|
} from '@/hooks/logic-hooks';
|
||||||
|
import { Message } from '@/interfaces/database/chat';
|
||||||
|
import { message } from 'antd';
|
||||||
|
import { get } from 'lodash';
|
||||||
import trim from 'lodash/trim';
|
import trim from 'lodash/trim';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useSearchParams } from 'umi';
|
import { useSearchParams } from 'umi';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
const isCompletionError = (res: any) =>
|
||||||
|
res && (res?.response.status !== 200 || res?.data?.code !== 0);
|
||||||
|
|
||||||
export const useSendButtonDisabled = (value: string) => {
|
export const useSendButtonDisabled = (value: string) => {
|
||||||
return trim(value) === '';
|
return trim(value) === '';
|
||||||
@ -30,36 +40,114 @@ export const useGetSharedChatSearchParams = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSendNextSharedMessage = (
|
export const useSendSharedMessage = () => {
|
||||||
addEventList: (data: IEventList, messageId: string) => void,
|
|
||||||
) => {
|
|
||||||
const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
|
|
||||||
const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`;
|
|
||||||
|
|
||||||
const [params, setParams] = useState<any[]>([]);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
visible: parameterDialogVisible,
|
from,
|
||||||
hideModal: hideParameterDialog,
|
sharedId: conversationId,
|
||||||
showModal: showParameterDialog,
|
data: data,
|
||||||
} = useSetModalState();
|
} = useGetSharedChatSearchParams();
|
||||||
|
const { createSharedConversation: setConversation } =
|
||||||
|
useCreateNextSharedConversation();
|
||||||
|
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
|
||||||
|
const { send, answer, done, stopOutputMessage } = useSendMessageWithSse(
|
||||||
|
`/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`,
|
||||||
|
);
|
||||||
|
const {
|
||||||
|
derivedMessages,
|
||||||
|
removeLatestMessage,
|
||||||
|
addNewestAnswer,
|
||||||
|
addNewestQuestion,
|
||||||
|
scrollRef,
|
||||||
|
messageContainerRef,
|
||||||
|
removeAllMessages,
|
||||||
|
} = useSelectDerivedMessages();
|
||||||
|
const [hasError, setHasError] = useState(false);
|
||||||
|
|
||||||
const ret = useSendAgentMessage(url, addEventList, params);
|
const sendMessage = useCallback(
|
||||||
|
async (message: Message, id?: string) => {
|
||||||
|
const res = await send({
|
||||||
|
conversation_id: id ?? conversationId,
|
||||||
|
quote: true,
|
||||||
|
question: message.content,
|
||||||
|
session_id: get(derivedMessages, '0.session_id'),
|
||||||
|
});
|
||||||
|
|
||||||
const ok = useCallback(
|
if (isCompletionError(res)) {
|
||||||
(params: any[]) => {
|
// cancel loading
|
||||||
setParams(params);
|
setValue(message.content);
|
||||||
hideParameterDialog();
|
removeLatestMessage();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[hideParameterDialog],
|
[send, conversationId, derivedMessages, setValue, removeLatestMessage],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSendMessage = useCallback(
|
||||||
|
async (message: Message) => {
|
||||||
|
if (conversationId !== '') {
|
||||||
|
sendMessage(message);
|
||||||
|
} else {
|
||||||
|
const data = await setConversation('user id');
|
||||||
|
if (data.code === 0) {
|
||||||
|
const id = data.data.id;
|
||||||
|
sendMessage(message, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[conversationId, setConversation, sendMessage],
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchSessionId = useCallback(async () => {
|
||||||
|
const payload = { question: '' };
|
||||||
|
const ret = await send({ ...payload, ...data });
|
||||||
|
if (isCompletionError(ret)) {
|
||||||
|
message.error(ret?.data.message);
|
||||||
|
setHasError(true);
|
||||||
|
}
|
||||||
|
}, [send]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchSessionId();
|
||||||
|
}, [fetchSessionId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (answer.answer) {
|
||||||
|
addNewestAnswer(answer);
|
||||||
|
}
|
||||||
|
}, [answer, addNewestAnswer]);
|
||||||
|
|
||||||
|
const handlePressEnter = useCallback(
|
||||||
|
(documentIds: string[]) => {
|
||||||
|
if (trim(value) === '') return;
|
||||||
|
const id = uuid();
|
||||||
|
if (done) {
|
||||||
|
setValue('');
|
||||||
|
addNewestQuestion({
|
||||||
|
content: value,
|
||||||
|
doc_ids: documentIds,
|
||||||
|
id,
|
||||||
|
role: MessageType.User,
|
||||||
|
});
|
||||||
|
handleSendMessage({
|
||||||
|
content: value.trim(),
|
||||||
|
id,
|
||||||
|
role: MessageType.User,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[addNewestQuestion, done, handleSendMessage, setValue, value],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...ret,
|
handlePressEnter,
|
||||||
hasError: false,
|
handleInputChange,
|
||||||
parameterDialogVisible,
|
value,
|
||||||
hideParameterDialog,
|
sendLoading: !done,
|
||||||
showParameterDialog,
|
loading: false,
|
||||||
ok,
|
derivedMessages,
|
||||||
|
hasError,
|
||||||
|
stopOutputMessage,
|
||||||
|
scrollRef,
|
||||||
|
messageContainerRef,
|
||||||
|
removeAllMessages,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,166 +1,75 @@
|
|||||||
import { FileUploadProps } from '@/components/file-upload';
|
import { EmbedContainer } from '@/components/embed-container';
|
||||||
import { NextMessageInput } from '@/components/message-input/next';
|
import { NextMessageInput } from '@/components/message-input/next';
|
||||||
import MessageItem from '@/components/next-message-item';
|
import MessageItem from '@/components/message-item';
|
||||||
import PdfDrawer from '@/components/pdf-drawer';
|
import PdfDrawer from '@/components/pdf-drawer';
|
||||||
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
import { MessageType, SharedFrom } from '@/constants/chat';
|
||||||
import { Button } from '@/components/ui/button';
|
import { useFetchNextConversationSSE } from '@/hooks/chat-hooks';
|
||||||
import { MessageType } from '@/constants/chat';
|
import { useFetchFlowSSE } from '@/hooks/flow-hooks';
|
||||||
import { useFetchAppConf } from '@/hooks/logic-hooks';
|
import { useFetchExternalChatInfo } from '@/hooks/use-chat-request';
|
||||||
import {
|
|
||||||
useFetchExternalAgentInputs,
|
|
||||||
useUploadCanvasFileWithProgress,
|
|
||||||
} from '@/hooks/use-agent-request';
|
|
||||||
import { cn } from '@/lib/utils';
|
|
||||||
import i18n from '@/locales/config';
|
import i18n from '@/locales/config';
|
||||||
import DebugContent from '@/pages/agent/debug-content';
|
|
||||||
import { useCacheChatLog } from '@/pages/agent/hooks/use-cache-chat-log';
|
|
||||||
import { useAwaitCompentData } from '@/pages/agent/hooks/use-chat-logic';
|
|
||||||
import { IInputs } from '@/pages/agent/interface';
|
|
||||||
import { useSendButtonDisabled } from '@/pages/chat/hooks';
|
import { useSendButtonDisabled } from '@/pages/chat/hooks';
|
||||||
import { buildMessageUuidWithRole } from '@/utils/chat';
|
import { buildMessageUuidWithRole } from '@/utils/chat';
|
||||||
import { isEmpty } from 'lodash';
|
import React, { forwardRef, useMemo } from 'react';
|
||||||
import { RefreshCcw } from 'lucide-react';
|
|
||||||
import React, { forwardRef, useCallback, useState } from 'react';
|
|
||||||
import {
|
import {
|
||||||
useGetSharedChatSearchParams,
|
useGetSharedChatSearchParams,
|
||||||
useSendNextSharedMessage,
|
useSendSharedMessage,
|
||||||
} from '../hooks/use-send-shared-message';
|
} from '../hooks/use-send-shared-message';
|
||||||
import { ParameterDialog } from './parameter-dialog';
|
import { buildMessageItemReference } from '../utils';
|
||||||
|
|
||||||
const ChatContainer = () => {
|
const ChatContainer = () => {
|
||||||
const {
|
const {
|
||||||
sharedId: conversationId,
|
sharedId: conversationId,
|
||||||
|
from,
|
||||||
locale,
|
locale,
|
||||||
visibleAvatar,
|
visibleAvatar,
|
||||||
} = useGetSharedChatSearchParams();
|
} = useGetSharedChatSearchParams();
|
||||||
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||||
useClickDrawer();
|
useClickDrawer();
|
||||||
|
|
||||||
const { uploadCanvasFile, loading } =
|
|
||||||
useUploadCanvasFileWithProgress(conversationId);
|
|
||||||
const {
|
|
||||||
addEventList,
|
|
||||||
setCurrentMessageId,
|
|
||||||
currentEventListWithoutMessageById,
|
|
||||||
clearEventList,
|
|
||||||
} = useCacheChatLog();
|
|
||||||
const {
|
const {
|
||||||
handlePressEnter,
|
handlePressEnter,
|
||||||
handleInputChange,
|
handleInputChange,
|
||||||
value,
|
value,
|
||||||
sendLoading,
|
sendLoading,
|
||||||
scrollRef,
|
|
||||||
messageContainerRef,
|
|
||||||
derivedMessages,
|
derivedMessages,
|
||||||
hasError,
|
hasError,
|
||||||
stopOutputMessage,
|
stopOutputMessage,
|
||||||
findReferenceByMessageId,
|
scrollRef,
|
||||||
appendUploadResponseList,
|
messageContainerRef,
|
||||||
parameterDialogVisible,
|
removeAllMessages,
|
||||||
showParameterDialog,
|
} = useSendSharedMessage();
|
||||||
sendFormMessage,
|
|
||||||
addNewestOneAnswer,
|
|
||||||
ok,
|
|
||||||
resetSession,
|
|
||||||
} = useSendNextSharedMessage(addEventList);
|
|
||||||
const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
|
|
||||||
derivedMessages,
|
|
||||||
sendFormMessage,
|
|
||||||
canvasId: conversationId as string,
|
|
||||||
});
|
|
||||||
const sendDisabled = useSendButtonDisabled(value);
|
const sendDisabled = useSendButtonDisabled(value);
|
||||||
const appConf = useFetchAppConf();
|
const { data: chatInfo } = useFetchExternalChatInfo();
|
||||||
const { data: inputsData } = useFetchExternalAgentInputs();
|
|
||||||
const [agentInfo, setAgentInfo] = useState<IInputs>({
|
|
||||||
avatar: '',
|
|
||||||
title: '',
|
|
||||||
inputs: {},
|
|
||||||
prologue: '',
|
|
||||||
});
|
|
||||||
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
|
|
||||||
useCallback(
|
|
||||||
async (files, options) => {
|
|
||||||
const ret = await uploadCanvasFile({ files, options });
|
|
||||||
appendUploadResponseList(ret.data, files);
|
|
||||||
},
|
|
||||||
[appendUploadResponseList, uploadCanvasFile],
|
|
||||||
);
|
|
||||||
|
|
||||||
|
const useFetchAvatar = useMemo(() => {
|
||||||
|
return from === SharedFrom.Agent
|
||||||
|
? useFetchFlowSSE
|
||||||
|
: useFetchNextConversationSSE;
|
||||||
|
}, [from]);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (locale && i18n.language !== locale) {
|
if (locale && i18n.language !== locale) {
|
||||||
i18n.changeLanguage(locale);
|
i18n.changeLanguage(locale);
|
||||||
}
|
}
|
||||||
}, [locale, visibleAvatar]);
|
}, [locale, visibleAvatar]);
|
||||||
|
const { data: avatarData } = useFetchAvatar();
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const { avatar, title, inputs } = inputsData;
|
|
||||||
setAgentInfo({
|
|
||||||
avatar,
|
|
||||||
title,
|
|
||||||
inputs: inputs,
|
|
||||||
prologue: '',
|
|
||||||
});
|
|
||||||
}, [inputsData, setAgentInfo]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (inputsData.prologue) {
|
|
||||||
addNewestOneAnswer({
|
|
||||||
answer: inputsData.prologue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [inputsData.prologue, addNewestOneAnswer]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) {
|
|
||||||
showParameterDialog();
|
|
||||||
}
|
|
||||||
}, [inputsData, showParameterDialog]);
|
|
||||||
|
|
||||||
const handleInputsModalOk = (params: any[]) => {
|
|
||||||
ok(params);
|
|
||||||
};
|
|
||||||
const handleReset = () => {
|
|
||||||
resetSession();
|
|
||||||
clearEventList();
|
|
||||||
};
|
|
||||||
if (!conversationId) {
|
if (!conversationId) {
|
||||||
return <div>empty</div>;
|
return <div>empty</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="h-[100vh] flex justify-center items-center">
|
<>
|
||||||
<div className="w-40 flex gap-2 absolute left-3 top-12 items-center">
|
<EmbedContainer
|
||||||
<img src="/logo.svg" alt="" />
|
title={chatInfo.title}
|
||||||
<span className="text-2xl font-bold">{appConf.appName}</span>
|
avatar={chatInfo.avatar}
|
||||||
</div>
|
handleReset={removeAllMessages}
|
||||||
<div className=" w-[80vw] border rounded-lg">
|
|
||||||
<div className="flex justify-between items-center border-b p-3">
|
|
||||||
<div className="flex gap-2 items-center">
|
|
||||||
<RAGFlowAvatar
|
|
||||||
avatar={agentInfo.avatar}
|
|
||||||
name={agentInfo.title}
|
|
||||||
isPerson
|
|
||||||
/>
|
|
||||||
<div className="text-xl text-foreground">{agentInfo.title}</div>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant={'secondary'}
|
|
||||||
className="text-sm text-foreground cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
handleReset();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="flex gap-1 items-center">
|
|
||||||
<RefreshCcw size={14} />
|
|
||||||
<span className="text-lg ">Reset</span>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3">
|
<div className="flex flex-1 flex-col p-2.5 h-[90vh] m-3">
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={
|
||||||
'flex flex-1 flex-col overflow-auto scrollbar-auto m-auto w-5/6',
|
'flex flex-1 flex-col overflow-auto scrollbar-auto m-auto w-5/6'
|
||||||
)}
|
}
|
||||||
ref={messageContainerRef}
|
ref={messageContainerRef}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
@ -168,51 +77,27 @@ const ChatContainer = () => {
|
|||||||
return (
|
return (
|
||||||
<MessageItem
|
<MessageItem
|
||||||
visibleAvatar={visibleAvatar}
|
visibleAvatar={visibleAvatar}
|
||||||
conversationId={conversationId}
|
|
||||||
currentEventListWithoutMessageById={
|
|
||||||
currentEventListWithoutMessageById
|
|
||||||
}
|
|
||||||
setCurrentMessageId={setCurrentMessageId}
|
|
||||||
key={buildMessageUuidWithRole(message)}
|
key={buildMessageUuidWithRole(message)}
|
||||||
|
avatarDialog={avatarData?.avatar}
|
||||||
item={message}
|
item={message}
|
||||||
nickname="You"
|
nickname="You"
|
||||||
reference={findReferenceByMessageId(message.id)}
|
reference={buildMessageItemReference(
|
||||||
|
{
|
||||||
|
message: derivedMessages,
|
||||||
|
reference: [],
|
||||||
|
},
|
||||||
|
message,
|
||||||
|
)}
|
||||||
loading={
|
loading={
|
||||||
message.role === MessageType.Assistant &&
|
message.role === MessageType.Assistant &&
|
||||||
sendLoading &&
|
sendLoading &&
|
||||||
derivedMessages?.length - 1 === i
|
derivedMessages?.length - 1 === i
|
||||||
}
|
}
|
||||||
isShare={true}
|
|
||||||
avatarDialog={agentInfo.avatar}
|
|
||||||
agentName={agentInfo.title}
|
|
||||||
index={i}
|
index={i}
|
||||||
clickDocumentButton={clickDocumentButton}
|
clickDocumentButton={clickDocumentButton}
|
||||||
showLikeButton={false}
|
showLikeButton={false}
|
||||||
showLoudspeaker={false}
|
showLoudspeaker={false}
|
||||||
showLog={false}
|
></MessageItem>
|
||||||
sendLoading={sendLoading}
|
|
||||||
>
|
|
||||||
{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>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@ -223,20 +108,20 @@ const ChatContainer = () => {
|
|||||||
<NextMessageInput
|
<NextMessageInput
|
||||||
isShared
|
isShared
|
||||||
value={value}
|
value={value}
|
||||||
disabled={hasError || isWaitting}
|
disabled={hasError}
|
||||||
sendDisabled={sendDisabled || isWaitting}
|
sendDisabled={sendDisabled}
|
||||||
conversationId={conversationId}
|
conversationId={conversationId}
|
||||||
onInputChange={handleInputChange}
|
onInputChange={handleInputChange}
|
||||||
onPressEnter={handlePressEnter}
|
onPressEnter={handlePressEnter}
|
||||||
sendLoading={sendLoading}
|
sendLoading={sendLoading}
|
||||||
|
uploadMethod="external_upload_and_parse"
|
||||||
|
showUploadIcon={false}
|
||||||
stopOutputMessage={stopOutputMessage}
|
stopOutputMessage={stopOutputMessage}
|
||||||
onUpload={handleUploadFile}
|
|
||||||
isUploading={loading || isWaitting}
|
|
||||||
></NextMessageInput>
|
></NextMessageInput>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</EmbedContainer>
|
||||||
{visible && (
|
{visible && (
|
||||||
<PdfDrawer
|
<PdfDrawer
|
||||||
visible={visible}
|
visible={visible}
|
||||||
@ -245,14 +130,7 @@ const ChatContainer = () => {
|
|||||||
chunk={selectedChunk}
|
chunk={selectedChunk}
|
||||||
></PdfDrawer>
|
></PdfDrawer>
|
||||||
)}
|
)}
|
||||||
{parameterDialogVisible && (
|
</>
|
||||||
<ParameterDialog
|
|
||||||
// hideModal={hideParameterDialog}
|
|
||||||
ok={handleInputsModalOk}
|
|
||||||
data={agentInfo.inputs}
|
|
||||||
></ParameterDialog>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useFetchTokenListBeforeOtherStep } from '@/components/embed-dialog/use-show-embed-dialog';
|
||||||
import HightLightMarkdown from '@/components/highlight-markdown';
|
import HightLightMarkdown from '@/components/highlight-markdown';
|
||||||
import { Modal } from '@/components/ui/modal/modal';
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
import { RAGFlowSelect } from '@/components/ui/select';
|
import { RAGFlowSelect } from '@/components/ui/select';
|
||||||
@ -9,7 +10,6 @@ import {
|
|||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useFetchTokenListBeforeOtherStep } from '../agent/hooks/use-show-dialog';
|
|
||||||
|
|
||||||
type IEmbedAppModalProps = {
|
type IEmbedAppModalProps = {
|
||||||
open: any;
|
open: any;
|
||||||
|
|||||||
@ -38,6 +38,8 @@ export enum Routes {
|
|||||||
ResultView = `${Chunk}${Result}`,
|
ResultView = `${Chunk}${Result}`,
|
||||||
KnowledgeGraph = '/knowledge-graph',
|
KnowledgeGraph = '/knowledge-graph',
|
||||||
AgentLogPage = '/agent-log-page',
|
AgentLogPage = '/agent-log-page',
|
||||||
|
AgentShare = '/agent/share',
|
||||||
|
ChatShare = `${Chats}/share`,
|
||||||
}
|
}
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
@ -57,8 +59,13 @@ const routes = [
|
|||||||
layout: false,
|
layout: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/next-chat/share',
|
path: Routes.ChatShare,
|
||||||
component: '@/pages/next-chats/share',
|
component: `@/pages${Routes.ChatShare}`,
|
||||||
|
layout: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: Routes.AgentShare,
|
||||||
|
component: `@/pages${Routes.AgentShare}`,
|
||||||
layout: false,
|
layout: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -28,6 +28,7 @@ const {
|
|||||||
getRelatedQuestions,
|
getRelatedQuestions,
|
||||||
listNextDialog,
|
listNextDialog,
|
||||||
upload_and_parse,
|
upload_and_parse,
|
||||||
|
fetchExternalChatInfo,
|
||||||
} = api;
|
} = api;
|
||||||
|
|
||||||
const methods = {
|
const methods = {
|
||||||
@ -131,6 +132,10 @@ const methods = {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
url: upload_and_parse,
|
url: upload_and_parse,
|
||||||
},
|
},
|
||||||
|
fetchExternalChatInfo: {
|
||||||
|
url: fetchExternalChatInfo,
|
||||||
|
method: 'get',
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const chatService = registerNextServer<keyof typeof methods>(methods);
|
const chatService = registerNextServer<keyof typeof methods>(methods);
|
||||||
|
|||||||
@ -111,6 +111,8 @@ export default {
|
|||||||
|
|
||||||
// next chat
|
// next chat
|
||||||
listNextDialog: `${api_host}/dialog/next`,
|
listNextDialog: `${api_host}/dialog/next`,
|
||||||
|
fetchExternalChatInfo: (id: string) =>
|
||||||
|
`${ExternalApi}${api_host}/chatbots/${id}/info`,
|
||||||
|
|
||||||
// file manager
|
// file manager
|
||||||
listFile: `${api_host}/file/list`,
|
listFile: `${api_host}/file/list`,
|
||||||
|
|||||||
Reference in New Issue
Block a user