perf: outlink config (#3128)

* update action

* perf: outlink config
This commit is contained in:
Archer 2024-11-12 15:56:53 +08:00 committed by archer
parent 73d28d1fc3
commit 5e273341dd
No known key found for this signature in database
GPG Key ID: 4446499B846D4A9E
38 changed files with 469 additions and 537 deletions

View File

@ -160,7 +160,7 @@ jobs:
docker buildx build \ docker buildx build \
-f projects/app/Dockerfile \ -f projects/app/Dockerfile \
--platform linux/amd64,linux/arm64 \ --platform linux/amd64,linux/arm64 \
--build-arg base_url=fastai \ --build-arg base_url=/fastai \
--label "org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT" \ --label "org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT" \
--label "org.opencontainers.image.description=fastgpt image" \ --label "org.opencontainers.image.description=fastgpt image" \
--push \ --push \

View File

@ -90,6 +90,7 @@ export const chats2GPTMessages = ({
} }
} else { } else {
const aiResults: ChatCompletionMessageParam[] = []; const aiResults: ChatCompletionMessageParam[] = [];
//AI //AI
item.value.forEach((value, i) => { item.value.forEach((value, i) => {
if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) { if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) {
@ -130,7 +131,7 @@ export const chats2GPTMessages = ({
if ( if (
lastValue && lastValue &&
lastValue.type === ChatItemValueTypeEnum.text && lastValue.type === ChatItemValueTypeEnum.text &&
typeof lastResult.content === 'string' typeof lastResult?.content === 'string'
) { ) {
lastResult.content += value.text.content; lastResult.content += value.text.content;
} else { } else {

View File

@ -10,7 +10,3 @@ export type AuthOutLinkLimitProps = AuthOutLinkChatProps & { outLink: OutLinkSch
export type AuthOutLinkResponse = { export type AuthOutLinkResponse = {
uid: string; uid: string;
}; };
export type AuthOutLinkProps = {
shareId?: string;
outLinkUid?: string;
};

View File

@ -54,7 +54,7 @@ export type OutLinkSchema<T extends OutlinkAppType = undefined> = {
// whether to hide the node status // whether to hide the node status
showNodeStatus: boolean; showNodeStatus: boolean;
// whether to show the complete quote // whether to show the complete quote
showCompleteQuote: boolean; showRawSource: boolean;
// response when request // response when request
immediateResponse?: string; immediateResponse?: string;
@ -84,7 +84,7 @@ export type OutLinkEditType<T = undefined> = {
name: string; name: string;
responseDetail?: OutLinkSchema<T>['responseDetail']; responseDetail?: OutLinkSchema<T>['responseDetail'];
showNodeStatus?: OutLinkSchema<T>['showNodeStatus']; showNodeStatus?: OutLinkSchema<T>['showNodeStatus'];
showCompleteQuote?: OutLinkSchema<T>['showCompleteQuote']; showRawSource?: OutLinkSchema<T>['showRawSource'];
// response when request // response when request
immediateResponse?: string; immediateResponse?: string;
// response when error or other situation // response when error or other situation

View File

@ -89,7 +89,7 @@ try {
// get chat logs; // get chat logs;
ChatSchema.index({ teamId: 1, appId: 1, updateTime: -1 }, { background: true }); ChatSchema.index({ teamId: 1, appId: 1, updateTime: -1 }, { background: true });
// get share chat history // get share chat history
ChatSchema.index({ shareId: 1, outLinkUid: 1, updateTime: -1, source: 1 }, { background: true }); ChatSchema.index({ shareId: 1, outLinkUid: 1, updateTime: -1 }, { background: true });
// timer, clear history // timer, clear history
ChatSchema.index({ teamId: 1, updateTime: -1 }, { background: true }); ChatSchema.index({ teamId: 1, updateTime: -1 }, { background: true });

View File

@ -42,27 +42,27 @@ export const getWorkflowResponseWrite = ({
if (!res || res.closed || !useStreamResponse) return; if (!res || res.closed || !useStreamResponse) return;
const detailEvent = [ // Forbid show detail
SseResponseEventEnum.error, const detailEvent: Record<string, 1> = {
SseResponseEventEnum.flowNodeStatus, [SseResponseEventEnum.error]: 1,
SseResponseEventEnum.flowResponses, [SseResponseEventEnum.flowNodeStatus]: 1,
SseResponseEventEnum.interactive, [SseResponseEventEnum.flowResponses]: 1,
SseResponseEventEnum.toolCall, [SseResponseEventEnum.interactive]: 1,
SseResponseEventEnum.toolParams, [SseResponseEventEnum.toolCall]: 1,
SseResponseEventEnum.toolResponse, [SseResponseEventEnum.toolParams]: 1,
SseResponseEventEnum.updateVariables [SseResponseEventEnum.toolResponse]: 1,
]; [SseResponseEventEnum.updateVariables]: 1
};
if (!detail && detailEvent[event]) return;
if (!detail && detailEvent.includes(event)) return; // Forbid show running status
const statusEvent: Record<string, 1> = {
if ( [SseResponseEventEnum.flowNodeStatus]: 1,
!showNodeStatus && [SseResponseEventEnum.toolCall]: 1,
(event === SseResponseEventEnum.flowNodeStatus || [SseResponseEventEnum.toolParams]: 1,
event === SseResponseEventEnum.toolCall || [SseResponseEventEnum.toolResponse]: 1
event === SseResponseEventEnum.toolParams || };
event === SseResponseEventEnum.toolResponse) if (!showNodeStatus && statusEvent[event]) return;
)
return;
responseWrite({ responseWrite({
res, res,

View File

@ -42,6 +42,7 @@ const OutLinkSchema = new Schema({
lastTime: { lastTime: {
type: Date type: Date
}, },
responseDetail: { responseDetail: {
type: Boolean, type: Boolean,
default: false default: false
@ -50,7 +51,7 @@ const OutLinkSchema = new Schema({
type: Boolean, type: Boolean,
default: false default: false
}, },
showCompleteQuote: { showRawSource: {
type: Boolean, type: Boolean,
default: false default: false
}, },
@ -70,6 +71,8 @@ const OutLinkSchema = new Schema({
type: String type: String
} }
}, },
// Third part app config
app: { app: {
type: Object // could be FeishuAppType | WecomAppType | ... type: Object // could be FeishuAppType | WecomAppType | ...
}, },

View File

@ -20,6 +20,7 @@
"official_account.edit_modal_title": "Edit WeChat Official Account Integration", "official_account.edit_modal_title": "Edit WeChat Official Account Integration",
"official_account.name": "WeChat Official Account Integration", "official_account.name": "WeChat Official Account Integration",
"official_account.params": "WeChat Official Account Parameters", "official_account.params": "WeChat Official Account Parameters",
"private_config": "Visibility configuration",
"publish_name": "Name", "publish_name": "Name",
"qpm_is_empty": "QPM cannot be empty", "qpm_is_empty": "QPM cannot be empty",
"qpm_tips": "Maximum number of queries per minute per IP", "qpm_tips": "Maximum number of queries per minute per IP",

View File

@ -28,7 +28,7 @@
"insert_input_guide,_some_data_already_exists": "有重复数据,已自动过滤,共插入 {{len}} 条数据", "insert_input_guide,_some_data_already_exists": "有重复数据,已自动过滤,共插入 {{len}} 条数据",
"is_chatting": "正在聊天中...请等待结束", "is_chatting": "正在聊天中...请等待结束",
"items": "条", "items": "条",
"module_runtime_and": "模块运行时间和", "module_runtime_and": "工作流总运行时间",
"multiple_AI_conversations": "多组 AI 对话", "multiple_AI_conversations": "多组 AI 对话",
"new_input_guide_lexicon": "新词库", "new_input_guide_lexicon": "新词库",
"no_workflow_response": "没有运行数据", "no_workflow_response": "没有运行数据",

View File

@ -20,10 +20,14 @@
"official_account.edit_modal_title": "编辑微信公众号接入", "official_account.edit_modal_title": "编辑微信公众号接入",
"official_account.name": "微信公众号接入", "official_account.name": "微信公众号接入",
"official_account.params": "微信公众号参数", "official_account.params": "微信公众号参数",
"private_config": "可见度配置",
"publish_name": "名称", "publish_name": "名称",
"qpm_is_empty": "QPM 不能为空", "qpm_is_empty": "QPM 不能为空",
"qpm_tips": "每个 IP 每分钟最多提问多少次", "qpm_tips": "每个 IP 每分钟最多提问多少次",
"quote_content": "知识库引用",
"request_address": "请求地址", "request_address": "请求地址",
"show_node": "实时运行状态",
"show_origin_content": "查看来源原文",
"show_share_link_modal_title": "开始使用", "show_share_link_modal_title": "开始使用",
"token_auth": "身份验证", "token_auth": "身份验证",
"token_auth_tips": "身份校验服务器地址", "token_auth_tips": "身份校验服务器地址",
@ -33,8 +37,5 @@
"wecom.bot_desc": "通过 API 直接接入企业微信机器人", "wecom.bot_desc": "通过 API 直接接入企业微信机器人",
"wecom.create_modal_title": "创建企微机器人", "wecom.create_modal_title": "创建企微机器人",
"wecom.edit_modal_title": "编辑企微机器人", "wecom.edit_modal_title": "编辑企微机器人",
"wecom.title": "发布到企业微信机器人", "wecom.title": "发布到企业微信机器人"
"show_node": "实时运行状态",
"quote_content": "引用内容",
"show_origin_content": "查看来源原文"
} }

View File

@ -34,7 +34,9 @@ export type ChatProviderProps = OutLinkChatAuthProps & {
// not chat test params // not chat test params
chatId?: string; chatId?: string;
chatType?: 'log' | 'chat' | 'share' | 'team'; chatType: 'log' | 'chat' | 'share' | 'team';
showRawSource: boolean;
showNodeStatus: boolean;
}; };
type useChatStoreType = OutLinkChatAuthProps & type useChatStoreType = OutLinkChatAuthProps &
@ -139,6 +141,8 @@ const Provider = ({
setChatHistories, setChatHistories,
variablesForm, variablesForm,
chatType = 'chat', chatType = 'chat',
showRawSource,
showNodeStatus,
chatConfig = {}, chatConfig = {},
children, children,
...props ...props
@ -241,7 +245,9 @@ const Provider = ({
outLinkAuthData, outLinkAuthData,
variablesForm, variablesForm,
getHistoryResponseData, getHistoryResponseData,
chatType chatType,
showRawSource,
showNodeStatus
}; };
return <ChatBoxContext.Provider value={value}>{children}</ChatBoxContext.Provider>; return <ChatBoxContext.Provider value={value}>{children}</ChatBoxContext.Provider>;

View File

@ -137,7 +137,9 @@ const ChatItem = (props: Props) => {
}; };
const { t } = useTranslation(); const { t } = useTranslation();
const { isChatting, chatType } = useContextSelector(ChatBoxContext, (v) => v); const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting);
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
const showNodeStatus = useContextSelector(ChatBoxContext, (v) => v.showNodeStatus);
const isChatLog = chatType === 'log'; const isChatLog = chatType === 'log';
const { copyData } = useCopyData(); const { copyData } = useCopyData();
@ -237,7 +239,7 @@ const ChatItem = (props: Props) => {
<ChatAvatar src={avatar} type={type} /> <ChatAvatar src={avatar} type={type} />
{/* Workflow status */} {/* Workflow status */}
{!!chatStatusMap && statusBoxData && isLastChild && ( {!!chatStatusMap && statusBoxData && isLastChild && showNodeStatus && (
<Flex <Flex
alignItems={'center'} alignItems={'center'}
px={3} px={3}

View File

@ -54,6 +54,7 @@ const ContextModal = ({ onClose, dataId }: { onClose: () => void; dataId: string
border={'base'} border={'base'}
_notLast={{ mb: 2 }} _notLast={{ mb: 2 }}
position={'relative'} position={'relative'}
bg={i % 2 === 0 ? 'white' : 'myGray.50'}
> >
<Box fontWeight={'bold'}>{item.obj}</Box> <Box fontWeight={'bold'}>{item.obj}</Box>
<Box>{item.value}</Box> <Box>{item.value}</Box>

View File

@ -11,12 +11,14 @@ import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
const QuoteModal = ({ const QuoteModal = ({
rawSearch = [], rawSearch = [],
onClose, onClose,
showDetail, canEditDataset,
showRawSource,
metadata metadata
}: { }: {
rawSearch: SearchDataResponseItemType[]; rawSearch: SearchDataResponseItemType[];
onClose: () => void; onClose: () => void;
showDetail: boolean; canEditDataset: boolean;
showRawSource: boolean;
metadata?: { metadata?: {
collectionId: string; collectionId: string;
sourceId?: string; sourceId?: string;
@ -47,7 +49,7 @@ const QuoteModal = ({
title={ title={
<Box> <Box>
{metadata ? ( {metadata ? (
<RawSourceBox {...metadata} canView={showDetail} /> <RawSourceBox {...metadata} canView={showRawSource} />
) : ( ) : (
<>{t('common:core.chat.Quote Amount', { amount: rawSearch.length })}</> <>{t('common:core.chat.Quote Amount', { amount: rawSearch.length })}</>
)} )}
@ -58,7 +60,11 @@ const QuoteModal = ({
} }
> >
<ModalBody> <ModalBody>
<QuoteList rawSearch={filterResults} showDetail={showDetail} /> <QuoteList
rawSearch={filterResults}
canEditDataset={canEditDataset}
canViewSource={showRawSource}
/>
</ModalBody> </ModalBody>
</MyModal> </MyModal>
</> </>
@ -69,10 +75,12 @@ export default QuoteModal;
export const QuoteList = React.memo(function QuoteList({ export const QuoteList = React.memo(function QuoteList({
rawSearch = [], rawSearch = [],
showDetail canEditDataset,
canViewSource
}: { }: {
rawSearch: SearchDataResponseItemType[]; rawSearch: SearchDataResponseItemType[];
showDetail: boolean; canEditDataset: boolean;
canViewSource: boolean;
}) { }) {
const theme = useTheme(); const theme = useTheme();
@ -89,7 +97,11 @@ export const QuoteList = React.memo(function QuoteList({
_hover={{ '& .hover-data': { display: 'flex' } }} _hover={{ '& .hover-data': { display: 'flex' } }}
bg={i % 2 === 0 ? 'white' : 'myWhite.500'} bg={i % 2 === 0 ? 'white' : 'myWhite.500'}
> >
<QuoteItem quoteItem={item} canViewSource={showDetail} linkToDataset={showDetail} /> <QuoteItem
quoteItem={item}
canViewSource={canViewSource}
canEditDataset={canEditDataset}
/>
</Box> </Box>
))} ))}
</> </>

View File

@ -7,13 +7,11 @@ import MyTag from '@fastgpt/web/components/common/Tag/index';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils'; import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
import ChatBoxDivider from '@/components/core/chat/Divider'; import ChatBoxDivider from '@/components/core/chat/Divider';
import { strIsLink } from '@fastgpt/global/common/string/tools';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { ChatSiteItemType } from '@fastgpt/global/core/chat/type'; import { ChatSiteItemType } from '@fastgpt/global/core/chat/type';
import { addStatisticalDataToHistoryItem } from '@/global/core/chat/utils'; import { addStatisticalDataToHistoryItem } from '@/global/core/chat/utils';
import { useSize } from 'ahooks'; import { useSize } from 'ahooks';
import { ChatContext } from '@/web/core/chat/context/chatContext';
import { useContextSelector } from 'use-context-selector'; import { useContextSelector } from 'use-context-selector';
import { ChatBoxContext } from '../Provider'; import { ChatBoxContext } from '../Provider';
@ -23,11 +21,9 @@ const WholeResponseModal = dynamic(() => import('../../../components/WholeRespon
const ResponseTags = ({ const ResponseTags = ({
showTags, showTags,
showDetail,
historyItem historyItem
}: { }: {
showTags: boolean; showTags: boolean;
showDetail: boolean;
historyItem: ChatSiteItemType; historyItem: ChatSiteItemType;
}) => { }) => {
const { isPc } = useSystem(); const { isPc } = useSystem();
@ -51,12 +47,9 @@ const ResponseTags = ({
}>(); }>();
const [quoteFolded, setQuoteFolded] = useState<boolean>(true); const [quoteFolded, setQuoteFolded] = useState<boolean>(true);
const showCompleteQuote = useContextSelector(ChatContext, (v) => v.showCompleteQuote); const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
const { chatType } = useContextSelector(ChatBoxContext, (v) => v); const showRawSource = useContextSelector(ChatBoxContext, (v) => v.showRawSource);
const notSharePage = useMemo(() => chatType !== 'share', [chatType]);
const showAllTag = useMemo(() => {
return chatType !== 'share' && chatType !== 'team';
}, [chatType]);
const { const {
isOpen: isOpenWholeModal, isOpen: isOpenWholeModal,
@ -88,13 +81,20 @@ const ResponseTags = ({
sourceName: item.sourceName, sourceName: item.sourceName,
sourceId: item.sourceId, sourceId: item.sourceId,
icon: getSourceNameIcon({ sourceId: item.sourceId, sourceName: item.sourceName }), icon: getSourceNameIcon({ sourceId: item.sourceId, sourceName: item.sourceName }),
canReadQuote: showCompleteQuote || strIsLink(item.sourceId),
collectionId: item.collectionId collectionId: item.collectionId
})); }));
}, [quoteList, showCompleteQuote]); }, [quoteList]);
const notEmptyTags =
quoteList.length > 0 ||
(llmModuleAccount === 1 && notSharePage) ||
(llmModuleAccount > 1 && notSharePage) ||
(isPc && runningTime > 0) ||
notSharePage;
return !showTags ? null : ( return !showTags ? null : (
<> <>
{/* quote */}
{sourceList.length > 0 && ( {sourceList.length > 0 && (
<> <>
<Flex justifyContent={'space-between'} alignItems={'center'}> <Flex justifyContent={'space-between'} alignItems={'center'}>
@ -188,74 +188,74 @@ const ResponseTags = ({
</> </>
)} )}
<Flex alignItems={'center'} mt={3} flexWrap={'wrap'} gap={2}> {notEmptyTags && (
{quoteList.length > 0 && ( <Flex alignItems={'center'} mt={3} flexWrap={'wrap'} gap={2}>
<MyTooltip label={t('chat:view_citations')}> {quoteList.length > 0 && (
<MyTag <MyTooltip label={t('chat:view_citations')}>
colorSchema="blue" <MyTag
type="borderSolid" colorSchema="blue"
cursor={'pointer'} type="borderSolid"
onClick={() => setQuoteModalData({ rawSearch: quoteList })} cursor={'pointer'}
> onClick={() => setQuoteModalData({ rawSearch: quoteList })}
{t('chat:citations', { num: quoteList.length })} >
{t('chat:citations', { num: quoteList.length })}
</MyTag>
</MyTooltip>
)}
{llmModuleAccount === 1 && notSharePage && (
<>
{historyPreviewLength > 0 && (
<MyTooltip label={t('chat:click_contextual_preview')}>
<MyTag
colorSchema="green"
cursor={'pointer'}
type="borderSolid"
onClick={onOpenContextModal}
>
{t('chat:contextual', { num: historyPreviewLength })}
</MyTag>
</MyTooltip>
)}
</>
)}
{llmModuleAccount > 1 && notSharePage && (
<MyTag type="borderSolid" colorSchema="blue">
{t('chat:multiple_AI_conversations')}
</MyTag> </MyTag>
</MyTooltip> )}
)} {isPc && runningTime > 0 && (
{llmModuleAccount === 1 && showAllTag && ( <MyTooltip label={t('chat:module_runtime_and')}>
<> <MyTag colorSchema="purple" type="borderSolid" cursor={'default'}>
{historyPreviewLength > 0 && ( {runningTime}s
<MyTooltip label={t('chat:click_contextual_preview')}> </MyTag>
<MyTag </MyTooltip>
colorSchema="green" )}
cursor={'pointer'}
type="borderSolid"
onClick={onOpenContextModal}
>
{t('chat:contextual', { num: historyPreviewLength })}
</MyTag>
</MyTooltip>
)}
</>
)}
{llmModuleAccount > 1 && showAllTag && (
<MyTag type="borderSolid" colorSchema="blue">
{t('chat:multiple_AI_conversations')}
</MyTag>
)}
{isPc && runningTime > 0 && ( {notSharePage && (
<MyTooltip label={t('chat:module_runtime_and')}> <MyTooltip label={t('common:core.chat.response.Read complete response tips')}>
<MyTag colorSchema="purple" type="borderSolid" cursor={'default'}> <MyTag
{runningTime}s colorSchema="gray"
</MyTag> type="borderSolid"
</MyTooltip> cursor={'pointer'}
)} onClick={onOpenWholeModal}
>
{showAllTag && ( {t('common:core.chat.response.Read complete response')}
<MyTooltip label={t('common:core.chat.response.Read complete response tips')}> </MyTag>
<MyTag </MyTooltip>
colorSchema="gray" )}
type="borderSolid" </Flex>
cursor={'pointer'} )}
onClick={onOpenWholeModal}
>
{t('common:core.chat.response.Read complete response')}
</MyTag>
</MyTooltip>
)}
</Flex>
{!!quoteModalData && ( {!!quoteModalData && (
<QuoteModal <QuoteModal
{...quoteModalData} {...quoteModalData}
showDetail={showCompleteQuote} canEditDataset={notSharePage}
showRawSource={showRawSource}
onClose={() => setQuoteModalData(undefined)} onClose={() => setQuoteModalData(undefined)}
/> />
)} )}
{isOpenContextModal && <ContextModal dataId={dataId} onClose={onCloseContextModal} />} {isOpenContextModal && <ContextModal dataId={dataId} onClose={onCloseContextModal} />}
{isOpenWholeModal && ( {isOpenWholeModal && <WholeResponseModal dataId={dataId} onClose={onCloseWholeModal} />}
<WholeResponseModal dataId={dataId} showDetail={true} onClose={onCloseWholeModal} />
)}
</> </>
); );
}; };

View File

@ -566,6 +566,7 @@ const ChatBox = (
// tts audio // tts audio
autoTTSResponse && splitText2Audio(responseText, true); autoTTSResponse && splitText2Audio(responseText, true);
} catch (err: any) { } catch (err: any) {
console.log(err);
toast({ toast({
title: t(getErrText(err, 'core.chat.error.Chat error') as any), title: t(getErrText(err, 'core.chat.error.Chat error') as any),
status: 'error', status: 'error',
@ -948,7 +949,6 @@ const ChatBox = (
> >
<ResponseTags <ResponseTags
showTags={index !== chatHistories.length - 1 || !isChatting} showTags={index !== chatHistories.length - 1 || !isChatting}
showDetail={!shareId && !teamId}
historyItem={item} historyItem={item}
/> />

View File

@ -31,12 +31,10 @@ type sideTabItemType = {
/* Per response value */ /* Per response value */
export const WholeResponseContent = ({ export const WholeResponseContent = ({
activeModule, activeModule,
hideTabs, hideTabs
showDetail
}: { }: {
activeModule: ChatHistoryItemResType; activeModule: ChatHistoryItemResType;
hideTabs?: boolean; hideTabs?: boolean;
showDetail: boolean;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -233,7 +231,7 @@ export const WholeResponseContent = ({
{activeModule.quoteList && activeModule.quoteList.length > 0 && ( {activeModule.quoteList && activeModule.quoteList.length > 0 && (
<Row <Row
label={t('common:core.chat.response.module quoteList')} label={t('common:core.chat.response.module quoteList')}
rawDom={<QuoteList showDetail={showDetail} rawSearch={activeModule.quoteList} />} rawDom={<QuoteList canEditDataset canViewSource rawSearch={activeModule.quoteList} />}
/> />
)} )}
</> </>
@ -531,12 +529,10 @@ const SideTabItem = ({
/* Modal main container */ /* Modal main container */
export const ResponseBox = React.memo(function ResponseBox({ export const ResponseBox = React.memo(function ResponseBox({
response, response,
showDetail,
hideTabs = false, hideTabs = false,
useMobile = false useMobile = false
}: { }: {
response: ChatHistoryItemResType[]; response: ChatHistoryItemResType[];
showDetail: boolean;
hideTabs?: boolean; hideTabs?: boolean;
useMobile?: boolean; useMobile?: boolean;
}) { }) {
@ -659,11 +655,7 @@ export const ResponseBox = React.memo(function ResponseBox({
</Box> </Box>
</Box> </Box>
<Box flex={'5 0 0'} w={0} height={'100%'}> <Box flex={'5 0 0'} w={0} height={'100%'}>
<WholeResponseContent <WholeResponseContent activeModule={activeModule} hideTabs={hideTabs} />
activeModule={activeModule}
hideTabs={hideTabs}
showDetail={showDetail}
/>
</Box> </Box>
</Flex> </Flex>
) : ( ) : (
@ -723,11 +715,7 @@ export const ResponseBox = React.memo(function ResponseBox({
</Box> </Box>
</Flex> </Flex>
<Box flex={'1 0 0'}> <Box flex={'1 0 0'}>
<WholeResponseContent <WholeResponseContent activeModule={activeModule} hideTabs={hideTabs} />
activeModule={activeModule}
hideTabs={hideTabs}
showDetail={showDetail}
/>
</Box> </Box>
</Flex> </Flex>
)} )}
@ -737,15 +725,7 @@ export const ResponseBox = React.memo(function ResponseBox({
); );
}); });
const WholeResponseModal = ({ const WholeResponseModal = ({ onClose, dataId }: { onClose: () => void; dataId: string }) => {
showDetail,
onClose,
dataId
}: {
showDetail: boolean;
onClose: () => void;
dataId: string;
}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { getHistoryResponseData } = useContextSelector(ChatBoxContext, (v) => v); const { getHistoryResponseData } = useContextSelector(ChatBoxContext, (v) => v);
@ -774,7 +754,7 @@ const WholeResponseModal = ({
} }
> >
{!!response?.length ? ( {!!response?.length ? (
<ResponseBox response={response} showDetail={showDetail} /> <ResponseBox response={response} />
) : ( ) : (
<EmptyTip text={t('chat:no_workflow_response')} /> <EmptyTip text={t('chat:no_workflow_response')} />
)} )}

View File

@ -9,8 +9,6 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import MyBox from '@fastgpt/web/components/common/MyBox'; import MyBox from '@fastgpt/web/components/common/MyBox';
import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/dataset/constants'; import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/dataset/constants';
import { useContextSelector } from 'use-context-selector';
import { ChatBoxContext } from '../chat/ChatContainer/ChatBox/Provider';
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal')); const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
@ -47,21 +45,15 @@ const scoreTheme: Record<
const QuoteItem = ({ const QuoteItem = ({
quoteItem, quoteItem,
canViewSource, canViewSource,
linkToDataset canEditDataset
}: { }: {
quoteItem: SearchDataResponseItemType; quoteItem: SearchDataResponseItemType;
canViewSource?: boolean; canViewSource?: boolean;
linkToDataset?: boolean; canEditDataset?: boolean;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [editInputData, setEditInputData] = useState<{ dataId: string; collectionId: string }>(); const [editInputData, setEditInputData] = useState<{ dataId: string; collectionId: string }>();
const { chatType } = useContextSelector(ChatBoxContext, (v) => v);
const canEdit = useMemo(() => {
return chatType !== 'share' && chatType !== 'team';
}, [chatType]);
const score = useMemo(() => { const score = useMemo(() => {
if (!Array.isArray(quoteItem.score)) { if (!Array.isArray(quoteItem.score)) {
return { return {
@ -118,89 +110,64 @@ const QuoteItem = ({
> >
<Flex alignItems={'center'} mb={3} flexWrap={'wrap'} gap={3}> <Flex alignItems={'center'} mb={3} flexWrap={'wrap'} gap={3}>
{score?.primaryScore && ( {score?.primaryScore && (
<> <MyTooltip label={t(SearchScoreTypeMap[score.primaryScore.type]?.desc as any)}>
{canViewSource ? ( <Flex
<MyTooltip label={t(SearchScoreTypeMap[score.primaryScore.type]?.desc as any)}> px={'12px'}
<Flex py={'5px'}
px={'12px'} borderRadius={'md'}
py={'5px'} color={'primary.700'}
borderRadius={'md'} bg={'primary.50'}
color={'primary.700'} borderWidth={'1px'}
bg={'primary.50'} borderColor={'primary.200'}
borderWidth={'1px'} alignItems={'center'}
borderColor={'primary.200'} fontSize={'sm'}
alignItems={'center'} >
fontSize={'sm'} <Box>#{score.primaryScore.index + 1}</Box>
> <Box borderRightColor={'primary.700'} borderRightWidth={'1px'} h={'14px'} mx={2} />
<Box>#{score.primaryScore.index + 1}</Box> <Box>
<Box {t(SearchScoreTypeMap[score.primaryScore.type]?.label as any)}
borderRightColor={'primary.700'} {SearchScoreTypeMap[score.primaryScore.type]?.showScore
borderRightWidth={'1px'} ? ` ${score.primaryScore.value.toFixed(4)}`
h={'14px'} : ''}
mx={2}
/>
<Box>
{t(SearchScoreTypeMap[score.primaryScore.type]?.label as any)}
{SearchScoreTypeMap[score.primaryScore.type]?.showScore
? ` ${score.primaryScore.value.toFixed(4)}`
: ''}
</Box>
</Flex>
</MyTooltip>
) : (
<Flex
px={'12px'}
py={'1px'}
mr={4}
borderRadius={'md'}
color={'primary.700'}
bg={'primary.50'}
borderWidth={'1px'}
borderColor={'primary.200'}
alignItems={'center'}
fontSize={'sm'}
>
<Box>#{score.primaryScore.index + 1}</Box>
</Flex>
)}
</>
)}
{canViewSource &&
score.secondaryScore.map((item, i) => (
<MyTooltip key={item.type} label={t(SearchScoreTypeMap[item.type]?.desc as any)}>
<Box fontSize={'xs'}>
<Flex alignItems={'flex-start'} lineHeight={1.2} mb={1}>
<Box
px={'5px'}
borderWidth={'1px'}
borderRadius={'sm'}
mr={'2px'}
{...(scoreTheme[i] && scoreTheme[i])}
>
<Box transform={'scale(0.9)'}>#{item.index + 1}</Box>
</Box>
<Box transform={'scale(0.9)'}>
{t(SearchScoreTypeMap[item.type]?.label as any)}: {item.value.toFixed(4)}
</Box>
</Flex>
<Box h={'4px'}>
{SearchScoreTypeMap[item.type]?.showScore && (
<Progress
value={item.value * 100}
h={'4px'}
w={'100%'}
size="sm"
borderRadius={'20px'}
{...(scoreTheme[i] && {
colorScheme: scoreTheme[i].colorScheme
})}
bg="#E8EBF0"
/>
)}
</Box>
</Box> </Box>
</MyTooltip> </Flex>
))} </MyTooltip>
)}
{score.secondaryScore.map((item, i) => (
<MyTooltip key={item.type} label={t(SearchScoreTypeMap[item.type]?.desc as any)}>
<Box fontSize={'xs'}>
<Flex alignItems={'flex-start'} lineHeight={1.2} mb={1}>
<Box
px={'5px'}
borderWidth={'1px'}
borderRadius={'sm'}
mr={'2px'}
{...(scoreTheme[i] && scoreTheme[i])}
>
<Box transform={'scale(0.9)'}>#{item.index + 1}</Box>
</Box>
<Box transform={'scale(0.9)'}>
{t(SearchScoreTypeMap[item.type]?.label as any)}: {item.value.toFixed(4)}
</Box>
</Flex>
<Box h={'4px'}>
{SearchScoreTypeMap[item.type]?.showScore && (
<Progress
value={item.value * 100}
h={'4px'}
w={'100%'}
size="sm"
borderRadius={'20px'}
{...(scoreTheme[i] && {
colorScheme: scoreTheme[i].colorScheme
})}
bg="#E8EBF0"
/>
)}
</Box>
</Box>
</MyTooltip>
))}
</Flex> </Flex>
<Box flex={'1 0 0'}> <Box flex={'1 0 0'}>
@ -208,73 +175,71 @@ const QuoteItem = ({
<Box color={'myGray.600'}>{quoteItem.a}</Box> <Box color={'myGray.600'}>{quoteItem.a}</Box>
</Box> </Box>
{canViewSource && ( <Flex
<Flex alignItems={'center'}
alignItems={'center'} flexWrap={'wrap'}
flexWrap={'wrap'} mt={3}
mt={3} gap={4}
gap={4} color={'myGray.500'}
color={'myGray.500'} fontSize={'xs'}
fontSize={'xs'} >
> <MyTooltip label={t('common:core.dataset.Quote Length')}>
<MyTooltip label={t('common:core.dataset.Quote Length')}> <Flex alignItems={'center'}>
<Flex alignItems={'center'}> <MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
<MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} /> {quoteItem.q.length + (quoteItem.a?.length || 0)}
{quoteItem.q.length + (quoteItem.a?.length || 0)} </Flex>
</Flex> </MyTooltip>
</MyTooltip> <RawSourceBox
<RawSourceBox fontWeight={'bold'}
fontWeight={'bold'} color={'black'}
color={'black'} collectionId={quoteItem.collectionId}
collectionId={quoteItem.collectionId} sourceName={quoteItem.sourceName}
sourceName={quoteItem.sourceName} sourceId={quoteItem.sourceId}
sourceId={quoteItem.sourceId} canView={canViewSource}
canView={canViewSource} />
/> <Box flex={1} />
<Box flex={1} /> {quoteItem.id && canEditDataset && (
{quoteItem.id && canEdit && ( <MyTooltip label={t('common:core.dataset.data.Edit')}>
<MyTooltip label={t('common:core.dataset.data.Edit')}> <Box
<Box
className="hover-data"
visibility={'hidden'}
display={'flex'}
alignItems={'center'}
justifyContent={'center'}
>
<MyIcon
name={'edit'}
w={['16px', '18px']}
h={['16px', '18px']}
cursor={'pointer'}
color={'myGray.600'}
_hover={{
color: 'primary.600'
}}
onClick={() =>
setEditInputData({
dataId: quoteItem.id,
collectionId: quoteItem.collectionId
})
}
/>
</Box>
</MyTooltip>
)}
{linkToDataset && canEdit && (
<Link
as={NextLink}
className="hover-data" className="hover-data"
visibility={'hidden'} visibility={'hidden'}
display={'flex'}
alignItems={'center'} alignItems={'center'}
color={'primary.500'} justifyContent={'center'}
href={`/dataset/detail?datasetId=${quoteItem.datasetId}&currentTab=dataCard&collectionId=${quoteItem.collectionId}`}
> >
{t('common:core.dataset.Go Dataset')} <MyIcon
<MyIcon name={'common/rightArrowLight'} w={'10px'} /> name={'edit'}
</Link> w={['16px', '18px']}
)} h={['16px', '18px']}
</Flex> cursor={'pointer'}
)} color={'myGray.600'}
_hover={{
color: 'primary.600'
}}
onClick={() =>
setEditInputData({
dataId: quoteItem.id,
collectionId: quoteItem.collectionId
})
}
/>
</Box>
</MyTooltip>
)}
{canEditDataset && (
<Link
as={NextLink}
className="hover-data"
visibility={'hidden'}
alignItems={'center'}
color={'primary.500'}
href={`/dataset/detail?datasetId=${quoteItem.datasetId}&currentTab=dataCard&collectionId=${quoteItem.collectionId}`}
>
{t('common:core.dataset.Go Dataset')}
<MyIcon name={'common/rightArrowLight'} w={'10px'} />
</Link>
)}
</Flex>
</MyBox> </MyBox>
{editInputData && ( {editInputData && (

View File

@ -6,37 +6,35 @@ import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollect
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils'; import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import { useI18n } from '@/web/context/I18n'; import { useI18n } from '@/web/context/I18n';
import { ChatBoxContext } from '../chat/ChatContainer/ChatBox/Provider'; import { ShareChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { useContextSelector } from 'use-context-selector';
type Props = BoxProps & { type Props = BoxProps &
sourceName?: string; ShareChatAuthProps & {
collectionId: string; sourceName?: string;
sourceId?: string; collectionId: string;
canView?: boolean; sourceId?: string;
}; canView?: boolean;
};
const RawSourceBox = ({ const RawSourceBox = ({
sourceId, sourceId,
collectionId, collectionId,
sourceName = '', sourceName = '',
canView = true, canView = true,
shareId,
outLinkUid,
...props ...props
}: Props) => { }: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { fileT } = useI18n(); const { fileT } = useI18n();
const { shareId, outLinkUid, chatType } = useContextSelector(ChatBoxContext, (v) => v);
const canPreview = !!sourceId && canView; const canPreview = !!sourceId && canView;
const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]); const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]);
const read = getCollectionSourceAndOpen({ const read = getCollectionSourceAndOpen({
collectionId, collectionId,
authProps: { shareId,
shareId, outLinkUid
outLinkUid
},
isShare: chatType === 'share'
}); });
return ( return (

View File

@ -17,16 +17,8 @@ async function handler(
req: ApiRequestProps<getHistoriesBody, getHistoriesQuery>, req: ApiRequestProps<getHistoriesBody, getHistoriesQuery>,
res: ApiResponseType<any> res: ApiResponseType<any>
): Promise<PaginationResponse<getHistoriesResponse>> { ): Promise<PaginationResponse<getHistoriesResponse>> {
const { const { appId, shareId, outLinkUid, teamId, teamToken, offset, pageSize, source } =
appId, req.body as getHistoriesBody;
shareId,
outLinkUid,
teamId,
teamToken,
offset,
pageSize,
source = ChatSourceEnum.online
} = req.body as getHistoriesBody;
const match = await (async () => { const match = await (async () => {
if (shareId && outLinkUid) { if (shareId && outLinkUid) {
@ -35,7 +27,6 @@ async function handler(
return { return {
shareId, shareId,
outLinkUid: uid, outLinkUid: uid,
source: ChatSourceEnum.share,
updateTime: { updateTime: {
$gte: new Date(new Date().setDate(new Date().getDate() - 30)) $gte: new Date(new Date().setDate(new Date().getDate() - 30))
} }
@ -55,7 +46,7 @@ async function handler(
return { return {
tmbId, tmbId,
appId, appId,
source: source source
}; };
} }
})(); })();

View File

@ -9,7 +9,7 @@ import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { authChatCrud } from '@/service/support/permission/auth/chat'; import { authChatCrud } from '@/service/support/permission/auth/chat';
import { MongoApp } from '@fastgpt/service/core/app/schema'; import { MongoApp } from '@fastgpt/service/core/app/schema';
import { AppErrEnum } from '@fastgpt/global/common/error/code/app'; import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils'; import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils';
import { authOutLink } from '@/service/support/permission/auth/outLink'; import { authOutLink } from '@/service/support/permission/auth/outLink';
import { GetChatTypeEnum } from '@/global/core/chat/constants'; import { GetChatTypeEnum } from '@/global/core/chat/constants';
@ -70,9 +70,7 @@ async function handler(
[GetChatTypeEnum.normal]: `dataId obj value adminFeedback userBadFeedback userGoodFeedback time ${ [GetChatTypeEnum.normal]: `dataId obj value adminFeedback userBadFeedback userGoodFeedback time ${
DispatchNodeResponseKeyEnum.nodeResponse DispatchNodeResponseKeyEnum.nodeResponse
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`, } ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`,
[GetChatTypeEnum.outLink]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time ${ [GetChatTypeEnum.outLink]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time ${DispatchNodeResponseKeyEnum.nodeResponse}`,
shareChat?.responseDetail || isPlugin ? `${DispatchNodeResponseKeyEnum.nodeResponse}` : ''
} `,
[GetChatTypeEnum.team]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time ${DispatchNodeResponseKeyEnum.nodeResponse}` [GetChatTypeEnum.team]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time ${DispatchNodeResponseKeyEnum.nodeResponse}`
}; };
@ -85,10 +83,14 @@ async function handler(
}); });
// Remove important information // Remove important information
if (type === 'outLink' && app.type !== AppTypeEnum.plugin) { if (shareChat && app.type !== AppTypeEnum.plugin) {
histories.forEach((item) => { histories.forEach((item) => {
if (item.obj === ChatRoleEnum.AI) { if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData }); item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
if (shareChat.showNodeStatus === false) {
item.value = item.value.filter((v) => v.type !== ChatItemValueTypeEnum.tool);
}
} }
}); });
} }

View File

@ -2,7 +2,6 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response'; import { jsonRes } from '@fastgpt/service/common/response';
import type { InitChatResponse, InitOutLinkChatProps } from '@/global/core/chat/api.d'; import type { InitChatResponse, InitOutLinkChatProps } from '@/global/core/chat/api.d';
import { getGuideModule, getAppChatConfig } from '@fastgpt/global/core/workflow/utils'; import { getGuideModule, getAppChatConfig } from '@fastgpt/global/core/workflow/utils';
import { getChatModelNameListByModules } from '@/service/core/app/workflow';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema'; import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { authOutLink } from '@/service/support/permission/auth/outLink'; import { authOutLink } from '@/service/support/permission/auth/outLink';
import { MongoApp } from '@fastgpt/service/core/app/schema'; import { MongoApp } from '@fastgpt/service/core/app/schema';
@ -54,7 +53,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
storeWelcomeText: chat?.welcomeText, storeWelcomeText: chat?.welcomeText,
isPublicFetch: false isPublicFetch: false
}), }),
chatModels: getChatModelNameListByModules(nodes),
name: app.name, name: app.name,
avatar: app.avatar, avatar: app.avatar,
intro: app.intro, intro: app.intro,

View File

@ -5,15 +5,13 @@ import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant
import { createFileToken } from '@fastgpt/service/support/permission/controller'; import { createFileToken } from '@fastgpt/service/support/permission/controller';
import { BucketNameEnum, ReadFileBaseUrl } from '@fastgpt/global/common/file/constants'; import { BucketNameEnum, ReadFileBaseUrl } from '@fastgpt/global/common/file/constants';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api'; import { ShareChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { authOutLink } from '@/service/support/permission/auth/outLink';
export type readCollectionSourceQuery = {}; export type readCollectionSourceQuery = {};
export type readCollectionSourceBody = { export type readCollectionSourceBody = {
collectionId: string; collectionId: string;
isShare?: boolean; } & ShareChatAuthProps;
} & AuthOutLinkProps;
export type readCollectionSourceResponse = { export type readCollectionSourceResponse = {
type: 'url'; type: 'url';
@ -23,12 +21,6 @@ export type readCollectionSourceResponse = {
async function handler( async function handler(
req: ApiRequestProps<readCollectionSourceBody, readCollectionSourceQuery> req: ApiRequestProps<readCollectionSourceBody, readCollectionSourceQuery>
): Promise<readCollectionSourceResponse> { ): Promise<readCollectionSourceResponse> {
const { isShare, outLinkUid, shareId } = req.body;
if (isShare) {
await authOutLink({ shareId, outLinkUid });
}
const { collection, teamId, tmbId } = await authDatasetCollection({ const { collection, teamId, tmbId } = await authDatasetCollection({
req, req,
authToken: true, authToken: true,

View File

@ -24,7 +24,7 @@ export type OutLinkUpdateResponse = {};
async function handler( async function handler(
req: ApiRequestProps<OutLinkUpdateBody, OutLinkUpdateQuery> req: ApiRequestProps<OutLinkUpdateBody, OutLinkUpdateQuery>
): Promise<OutLinkUpdateResponse> { ): Promise<OutLinkUpdateResponse> {
const { _id, name, responseDetail, limit, app, showCompleteQuote, showNodeStatus } = req.body; const { _id, name, responseDetail, limit, app, showRawSource, showNodeStatus } = req.body;
if (!_id) { if (!_id) {
return Promise.reject(CommonErrEnum.missingParams); return Promise.reject(CommonErrEnum.missingParams);
@ -35,7 +35,7 @@ async function handler(
await MongoOutLink.findByIdAndUpdate(_id, { await MongoOutLink.findByIdAndUpdate(_id, {
name, name,
responseDetail, responseDetail,
showCompleteQuote, showRawSource,
showNodeStatus, showNodeStatus,
limit, limit,
app app

View File

@ -84,7 +84,6 @@ type AuthResponseType = {
app: AppSchema; app: AppSchema;
responseDetail?: boolean; responseDetail?: boolean;
showNodeStatus?: boolean; showNodeStatus?: boolean;
showCompleteQuote?: boolean;
authType: `${AuthUserTypeEnum}`; authType: `${AuthUserTypeEnum}`;
apikey?: string; apikey?: string;
canWrite: boolean; canWrite: boolean;

View File

@ -181,6 +181,8 @@ const DetailLogsModal = ({
appId={appId} appId={appId}
chatId={chatId} chatId={chatId}
chatType="log" chatType="log"
showRawSource
showNodeStatus
/> />
)} )}
</Box> </Box>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { import {
Flex, Flex,
Box, Box,
@ -32,7 +32,6 @@ import { useCopyData } from '@/web/common/hooks/useCopyData';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { defaultOutLinkForm } from '@/web/core/app/constants'; import { defaultOutLinkForm } from '@/web/core/app/constants';
import type { OutLinkEditType, OutLinkSchema } from '@fastgpt/global/support/outLink/type.d'; import type { OutLinkEditType, OutLinkSchema } from '@fastgpt/global/support/outLink/type.d';
import { useRequest } from '@/web/common/hooks/useRequest';
import { PublishChannelEnum } from '@fastgpt/global/support/outLink/constant'; import { PublishChannelEnum } from '@fastgpt/global/support/outLink/constant';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useToast } from '@fastgpt/web/hooks/useToast'; import { useToast } from '@fastgpt/web/hooks/useToast';
@ -48,6 +47,7 @@ import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import MyBox from '@fastgpt/web/components/common/MyBox'; import MyBox from '@fastgpt/web/components/common/MyBox';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal')); const SelectUsingWayModal = dynamic(() => import('./SelectUsingWayModal'));
@ -183,9 +183,9 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => {
setEditLinkData({ setEditLinkData({
_id: item._id, _id: item._id,
name: item.name, name: item.name,
responseDetail: item.responseDetail, responseDetail: item.responseDetail ?? false,
showCompleteQuote: item.showCompleteQuote, showRawSource: item.showRawSource ?? false,
showNodeStatus: item.showNodeStatus, showNodeStatus: item.showNodeStatus ?? false,
limit: item.limit limit: item.limit
}) })
}, },
@ -281,36 +281,23 @@ function EditLinkModal({
}); });
const responseDetail = watch('responseDetail'); const responseDetail = watch('responseDetail');
const showCompleteQuote = watch('showCompleteQuote'); const showRawSource = watch('showRawSource');
useEffect(() => {
if (!responseDetail) {
setValue('showCompleteQuote', false);
}
}, [responseDetail, setValue]);
useEffect(() => {
if (showCompleteQuote) {
setValue('responseDetail', true);
}
}, [showCompleteQuote, setValue]);
const isEdit = useMemo(() => !!defaultData._id, [defaultData]); const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
const { mutate: onclickCreate, isLoading: creating } = useRequest({ const { runAsync: onclickCreate, loading: creating } = useRequest2(
mutationFn: async (e: OutLinkEditType) => async (e: OutLinkEditType) =>
createShareChat({ createShareChat({
...e, ...e,
appId, appId,
type type
}), }),
errorToast: t('common:common.Create Failed'), {
onSuccess: onCreate errorToast: t('common:common.Create Failed'),
}); onSuccess: onCreate
const { mutate: onclickUpdate, isLoading: updating } = useRequest({ }
mutationFn: (e: OutLinkEditType) => { );
return putShareChat(e); const { runAsync: onclickUpdate, loading: updating } = useRequest2(putShareChat, {
},
errorToast: t('common:common.Update Failed'), errorToast: t('common:common.Update Failed'),
onSuccess: onEdit onSuccess: onEdit
}); });
@ -320,131 +307,133 @@ function EditLinkModal({
isOpen={true} isOpen={true}
iconSrc="/imgs/modal/shareFill.svg" iconSrc="/imgs/modal/shareFill.svg"
title={isEdit ? publishT('edit_link') : publishT('create_link')} title={isEdit ? publishT('edit_link') : publishT('create_link')}
w={'53.125rem'} maxW={['90vw', '700px']}
w={'100%'}
h={['90vh', 'auto']}
> >
<ModalBody p={6}> <ModalBody
<Flex flexDir={['column', 'row']}> p={6}
<Box pr={[0, 6]} borderRight={['0px', '1px']} borderColor={['', 'myGray.150']}> display={['block', 'flex']}
<Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}> flex={['1 0 0', 'auto']}
{t('publish:basic_info')} overflow={'auto'}
</Box> gap={4}
<Flex alignItems={'center'} mt={4}> >
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel> <Box pr={[0, 4]} flex={1} borderRight={['0px', '1px']} borderColor={['', 'myGray.150']}>
<Input <Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}>
placeholder={publishT('link_name')} {t('publish:basic_info')}
maxLength={20}
{...register('name', {
required: t('common:common.name_is_empty') || 'name_is_empty'
})}
/>
</Flex>
{feConfigs?.isPlus && (
<>
<Flex alignItems={'center'} mt={4}>
<FormLabel flex={'0 0 90px'} alignItems={'center'}>
{t('common:common.Expired Time')}
</FormLabel>
<Input
type="datetime-local"
defaultValue={
defaultData.limit?.expiredTime
? dayjs(defaultData.limit?.expiredTime).format('YYYY-MM-DDTHH:mm')
: ''
}
onChange={(e) => {
setValue('limit.expiredTime', new Date(e.target.value));
}}
/>
</Flex>
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>QPM</FormLabel>
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
</Flex>
<Input
max={1000}
{...register('limit.QPM', {
min: 0,
max: 1000,
valueAsNumber: true,
required: publishT('qpm_is_empty') || ''
})}
/>
</Flex>
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>{t('common:support.outlink.Max usage points')}</FormLabel>
<QuestionTip
ml={1}
label={t('common:support.outlink.Max usage points tip')}
></QuestionTip>
</Flex>
<Input
{...register('limit.maxUsagePoints', {
min: -1,
max: 10000000,
valueAsNumber: true,
required: true
})}
/>
</Flex>
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>{publishT('token_auth')}</FormLabel>
<QuestionTip ml={1} label={publishT('token_auth_tips') || ''}></QuestionTip>
</Flex>
<Input
placeholder={publishT('token_auth_tips') || ''}
fontSize={'sm'}
{...register('limit.hookUrl')}
/>
</Flex>
<Link
href={getDocPath('/docs/development/openapi/share')}
target={'_blank'}
fontSize={'xs'}
color={'myGray.500'}
>
{publishT('token_auth_use_cases')}
</Link>
</>
)}
</Box> </Box>
<Box pl={[0, 6]} flexGrow={1} pt={[6, 0]}> <Flex alignItems={'center'} mt={4}>
<Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}> <FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
{t('publish:config')} <Input
</Box> placeholder={publishT('link_name')}
<Flex alignItems={'center'} mt={4} justify={'space-between'}> maxLength={20}
<Flex alignItems={'center'}> {...register('name', {
<FormLabel>{t('publish:show_node')}</FormLabel> required: t('common:common.name_is_empty') || 'name_is_empty'
})}
/>
</Flex>
{feConfigs?.isPlus && (
<>
<Flex alignItems={'center'} mt={4}>
<FormLabel flex={'0 0 90px'} alignItems={'center'}>
{t('common:common.Expired Time')}
</FormLabel>
<Input
type="datetime-local"
defaultValue={
defaultData.limit?.expiredTime
? dayjs(defaultData.limit?.expiredTime).format('YYYY-MM-DDTHH:mm')
: ''
}
onChange={(e) => {
setValue('limit.expiredTime', new Date(e.target.value));
}}
/>
</Flex>
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>QPM</FormLabel>
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
</Flex>
<Input
max={1000}
{...register('limit.QPM', {
min: 0,
max: 1000,
valueAsNumber: true,
required: publishT('qpm_is_empty') || ''
})}
/>
</Flex>
<Flex alignItems={'center'} mt={4}>
<Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>{t('common:support.outlink.Max usage points')}</FormLabel>
<QuestionTip
ml={1}
label={t('common:support.outlink.Max usage points tip')}
></QuestionTip>
</Flex>
<Input
{...register('limit.maxUsagePoints', {
min: -1,
max: 10000000,
valueAsNumber: true,
required: true
})}
/>
</Flex> </Flex>
<Switch {...register('showNodeStatus')} />
</Flex>
<Flex alignItems={'center'} mt={4} justify={'space-between'}> <Flex alignItems={'center'} mt={4}>
<Flex alignItems={'center'}> <Flex flex={'0 0 90px'} alignItems={'center'}>
<FormLabel>{t('common:support.outlink.share.Response Quote')}</FormLabel> <FormLabel>{publishT('token_auth')}</FormLabel>
<QuestionTip <QuestionTip ml={1} label={publishT('token_auth_tips') || ''}></QuestionTip>
ml={1} </Flex>
label={t('common:support.outlink.share.Response Quote tips' || '')} <Input
></QuestionTip> placeholder={publishT('token_auth_tips') || ''}
fontSize={'sm'}
{...register('limit.hookUrl')}
/>
</Flex> </Flex>
<Switch {...register('responseDetail')} isChecked={responseDetail} /> <Link
</Flex> href={getDocPath('/docs/development/openapi/share')}
target={'_blank'}
<Flex alignItems={'center'} mt={4} justify={'space-between'}> fontSize={'xs'}
<Flex alignItems={'center'}> color={'myGray.500'}
<FormLabel>{t('common:support.outlink.share.show_complete_quote')}</FormLabel> >
<QuestionTip {publishT('token_auth_use_cases')}
ml={1} </Link>
label={t('common:support.outlink.share.show_complete_quote_tips' || '')} </>
></QuestionTip> )}
</Flex> </Box>
<Switch {...register('showCompleteQuote')} isChecked={showCompleteQuote} /> <Box flex={1} pt={[6, 0]}>
</Flex> <Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}>
{t('publish:private_config')}
</Box> </Box>
</Flex> <Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
<FormLabel>{t('publish:show_node')}</FormLabel>
<Switch {...register('showNodeStatus')} />
</Flex>
<Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
<Flex alignItems={'center'}>
<FormLabel>{t('common:support.outlink.share.Response Quote')}</FormLabel>
<QuestionTip
ml={1}
label={t('common:support.outlink.share.Response Quote tips' || '')}
></QuestionTip>
</Flex>
<Switch {...register('responseDetail')} isChecked={responseDetail} />
</Flex>
{/* <Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
<Flex alignItems={'center'}>
<FormLabel>{t('common:support.outlink.share.show_complete_quote')}</FormLabel>
<QuestionTip
ml={1}
label={t('common:support.outlink.share.show_complete_quote_tips' || '')}
></QuestionTip>
</Flex>
<Switch {...register('showRawSource')} isChecked={showRawSource} />
</Flex> */}
</Box>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>

View File

@ -113,6 +113,9 @@ export const useChatTest = ({
appAvatar={appDetail.avatar} appAvatar={appDetail.avatar}
userAvatar={userInfo?.avatar} userAvatar={userInfo?.avatar}
showMarkIcon showMarkIcon
chatType="chat"
showRawSource
showNodeStatus
chatConfig={chatConfig} chatConfig={chatConfig}
onStartChat={startChat} onStartChat={startChat}
onDelMessage={() => {}} onDelMessage={() => {}}

View File

@ -34,6 +34,7 @@ import { useChat } from '@/components/core/chat/ChatContainer/useChat';
import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import ChatBox from '@/components/core/chat/ChatContainer/ChatBox';
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { InitChatResponse } from '@/global/core/chat/api'; import { InitChatResponse } from '@/global/core/chat/api';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox')); const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
@ -283,6 +284,9 @@ const Chat = ({
onDelMessage={({ contentId }) => delChatRecordById({ contentId, appId, chatId })} onDelMessage={({ contentId }) => delChatRecordById({ contentId, appId, chatId })}
appId={appId} appId={appId}
chatId={chatId} chatId={chatId}
chatType={'chat'}
showRawSource
showNodeStatus
/> />
)} )}
</Box> </Box>
@ -341,7 +345,7 @@ const Render = (props: Props) => {
} }
}); });
const providerParams = useMemo(() => ({ appId }), [appId]); const providerParams = useMemo(() => ({ appId, source: ChatSourceEnum.online }), [appId]);
return ( return (
<ChatContextProvider params={providerParams}> <ChatContextProvider params={providerParams}>
<Chat {...props} myApps={myApps} /> <Chat {...props} myApps={myApps} />

View File

@ -42,7 +42,8 @@ type Props = {
shareId: string; shareId: string;
authToken: string; authToken: string;
customUid: string; customUid: string;
showCompleteQuote: boolean; showRawSource: boolean;
showNodeStatus: boolean;
}; };
const OutLink = ( const OutLink = (
@ -52,7 +53,7 @@ const OutLink = (
) => { ) => {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const { outLinkUid } = props; const { outLinkUid, showRawSource, showNodeStatus } = props;
const { const {
shareId = '', shareId = '',
chatId = '', chatId = '',
@ -366,6 +367,8 @@ const OutLink = (
shareId={shareId} shareId={shareId}
outLinkUid={outLinkUid} outLinkUid={outLinkUid}
chatType="share" chatType="share"
showRawSource={showRawSource}
showNodeStatus={showNodeStatus}
/> />
)} )}
</Box> </Box>
@ -377,13 +380,13 @@ const OutLink = (
}; };
const Render = (props: Props) => { const Render = (props: Props) => {
const { shareId, authToken, customUid, showCompleteQuote } = props; const { shareId, authToken, customUid } = props;
const { localUId, loaded } = useShareChatStore(); const { localUId, loaded } = useShareChatStore();
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
const contextParams = useMemo(() => { const contextParams = useMemo(() => {
return { shareId, outLinkUid: authToken || localUId || customUid, showCompleteQuote }; return { shareId, outLinkUid: authToken || localUId || customUid };
}, [authToken, customUid, localUId, shareId, showCompleteQuote]); }, [authToken, customUid, localUId, shareId]);
useMount(() => { useMount(() => {
setIsLoaded(true); setIsLoaded(true);
@ -417,7 +420,7 @@ export async function getServerSideProps(context: any) {
{ {
shareId shareId
}, },
'appId showCompleteQuote' 'appId showRawSource showNodeStatus'
) )
.populate('appId', 'name avatar intro') .populate('appId', 'name avatar intro')
.lean()) as OutLinkWithAppType; .lean()) as OutLinkWithAppType;
@ -433,7 +436,8 @@ export async function getServerSideProps(context: any) {
appName: app?.appId?.name ?? 'AI', appName: app?.appId?.name ?? 'AI',
appAvatar: app?.appId?.avatar ?? '', appAvatar: app?.appId?.avatar ?? '',
appIntro: app?.appId?.intro ?? 'AI', appIntro: app?.appId?.intro ?? 'AI',
showCompleteQuote: app?.showCompleteQuote ?? false, showRawSource: app?.showRawSource ?? false,
showNodeStatus: app?.showNodeStatus ?? false,
shareId: shareId ?? '', shareId: shareId ?? '',
authToken: authToken ?? '', authToken: authToken ?? '',
customUid, customUid,

View File

@ -297,6 +297,8 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
teamId={teamId} teamId={teamId}
teamToken={teamToken} teamToken={teamToken}
chatType="team" chatType="team"
showRawSource
showNodeStatus
/> />
)} )}
</Box> </Box>

View File

@ -26,11 +26,9 @@ import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { getDefaultIndex, getSourceNameIcon } from '@fastgpt/global/core/dataset/utils'; import { getDefaultIndex, getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
import { DatasetDataIndexItemType } from '@fastgpt/global/core/dataset/type'; import { DatasetDataIndexItemType } from '@fastgpt/global/core/dataset/type';
import SideTabs from '@/components/SideTabs';
import DeleteIcon from '@fastgpt/web/components/common/Icon/delete'; import DeleteIcon from '@fastgpt/web/components/common/Icon/delete';
import { defaultCollectionDetail } from '@/web/core/dataset/constants'; import { defaultCollectionDetail } from '@/web/core/dataset/constants';
import { getDocPath } from '@/web/common/system/doc'; import { getDocPath } from '@/web/common/system/doc';
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
import MyBox from '@fastgpt/web/components/common/MyBox'; import MyBox from '@fastgpt/web/components/common/MyBox';
import { getErrText } from '@fastgpt/global/common/error/utils'; import { getErrText } from '@fastgpt/global/common/error/utils';
import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useSystemStore } from '@/web/common/system/useSystemStore';

View File

@ -10,8 +10,6 @@ import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants'; import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants';
import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource'; import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import { useContextSelector } from 'use-context-selector';
import { ChatBoxContext } from '@/components/core/chat/ChatContainer/ChatBox/Provider';
const MetaDataCard = ({ datasetId }: { datasetId: string }) => { const MetaDataCard = ({ datasetId }: { datasetId: string }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -21,15 +19,8 @@ const MetaDataCard = ({ datasetId }: { datasetId: string }) => {
datasetId: string; datasetId: string;
}; };
const { shareId, outLinkUid, chatType } = useContextSelector(ChatBoxContext, (v) => v);
const readSource = getCollectionSourceAndOpen({ const readSource = getCollectionSourceAndOpen({
collectionId, collectionId
authProps: {
shareId,
outLinkUid
},
isShare: chatType === 'share'
}); });
const { data: collection, loading: isLoading } = useRequest2( const { data: collection, loading: isLoading } = useRequest2(
() => getDatasetCollectionById(collectionId), () => getDatasetCollectionById(collectionId),

View File

@ -3,9 +3,9 @@ import type {
AuthOutLinkChatProps, AuthOutLinkChatProps,
AuthOutLinkLimitProps, AuthOutLinkLimitProps,
AuthOutLinkInitProps, AuthOutLinkInitProps,
AuthOutLinkResponse, AuthOutLinkResponse
AuthOutLinkProps
} from '@fastgpt/global/support/outLink/api.d'; } from '@fastgpt/global/support/outLink/api.d';
import { ShareChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { authOutLinkValid } from '@fastgpt/service/support/permission/publish/authLink'; import { authOutLinkValid } from '@fastgpt/service/support/permission/publish/authLink';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team'; import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant'; import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
@ -24,7 +24,7 @@ export function authOutLinkChatLimit(data: AuthOutLinkLimitProps): Promise<AuthO
export const authOutLink = async ({ export const authOutLink = async ({
shareId, shareId,
outLinkUid outLinkUid
}: AuthOutLinkProps): Promise<{ }: ShareChatAuthProps): Promise<{
uid: string; uid: string;
appId: string; appId: string;
shareChat: OutLinkSchema; shareChat: OutLinkSchema;

View File

@ -24,7 +24,7 @@ export const defaultOutLinkForm: OutLinkEditType = {
name: '', name: '',
responseDetail: false, responseDetail: false,
showNodeStatus: false, showNodeStatus: false,
showCompleteQuote: false, showRawSource: false,
limit: { limit: {
QPM: 100, QPM: 100,
maxUsagePoints: -1 maxUsagePoints: -1

View File

@ -44,7 +44,6 @@ type ChatContextType = {
isLoading: boolean; isLoading: boolean;
histories: ChatHistoryItemType[]; histories: ChatHistoryItemType[];
onUpdateHistoryTitle: ({ chatId, newTitle }: { chatId: string; newTitle: string }) => void; onUpdateHistoryTitle: ({ chatId, newTitle }: { chatId: string; newTitle: string }) => void;
showCompleteQuote: boolean;
}; };
export const ChatContext = createContext<ChatContextType>({ export const ChatContext = createContext<ChatContextType>({
@ -86,8 +85,7 @@ export const ChatContext = createContext<ChatContextType>({
onChangeAppId: function (appId: string): void { onChangeAppId: function (appId: string): void {
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
}, },
isLoading: false, isLoading: false
showCompleteQuote: true
}); });
const ChatContextProvider = ({ const ChatContextProvider = ({
@ -96,7 +94,6 @@ const ChatContextProvider = ({
}: ChatContextValueType & { children: ReactNode }) => { }: ChatContextValueType & { children: ReactNode }) => {
const router = useRouter(); const router = useRouter();
const { chatId = '' } = router.query as { chatId: string }; const { chatId = '' } = router.query as { chatId: string };
const { showCompleteQuote }: { showCompleteQuote?: boolean } = params;
const forbidLoadChat = useRef(false); const forbidLoadChat = useRef(false);
@ -228,8 +225,7 @@ const ChatContextProvider = ({
ScrollData, ScrollData,
loadHistories, loadHistories,
histories, histories,
onUpdateHistoryTitle, onUpdateHistoryTitle
showCompleteQuote: showCompleteQuote ?? true
}; };
return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>; return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>;
}; };

View File

@ -34,10 +34,7 @@ import type { CreateDatasetParams, InsertOneDatasetDataProps } from '@/global/co
import type { DatasetCollectionItemType } from '@fastgpt/global/core/dataset/type'; import type { DatasetCollectionItemType } from '@fastgpt/global/core/dataset/type';
import { DatasetCollectionSyncResultEnum } from '@fastgpt/global/core/dataset/constants'; import { DatasetCollectionSyncResultEnum } from '@fastgpt/global/core/dataset/constants';
import type { DatasetDataItemType } from '@fastgpt/global/core/dataset/type'; import type { DatasetDataItemType } from '@fastgpt/global/core/dataset/type';
import type { import type { DatasetCollectionsListItemType } from '@/global/core/dataset/type.d';
DatasetCollectionsListItemType,
DatasetDataListItemType
} from '@/global/core/dataset/type.d';
import { PagingData } from '@/types'; import { PagingData } from '@/types';
import type { getDatasetTrainingQueueResponse } from '@/pages/api/core/dataset/training/getDatasetTrainingQueue'; import type { getDatasetTrainingQueueResponse } from '@/pages/api/core/dataset/training/getDatasetTrainingQueue';
import type { rebuildEmbeddingBody } from '@/pages/api/core/dataset/training/rebuildEmbedding'; import type { rebuildEmbeddingBody } from '@/pages/api/core/dataset/training/rebuildEmbedding';
@ -45,7 +42,10 @@ import type {
PostPreviewFilesChunksProps, PostPreviewFilesChunksProps,
PreviewChunksResponse PreviewChunksResponse
} from '@/pages/api/core/dataset/file/getPreviewChunks'; } from '@/pages/api/core/dataset/file/getPreviewChunks';
import type { readCollectionSourceResponse } from '@/pages/api/core/dataset/collection/read'; import type {
readCollectionSourceBody,
readCollectionSourceResponse
} from '@/pages/api/core/dataset/collection/read';
import type { GetDatasetListBody } from '@/pages/api/core/dataset/list'; import type { GetDatasetListBody } from '@/pages/api/core/dataset/list';
import type { UpdateDatasetCollectionParams } from '@/pages/api/core/dataset/collection/update'; import type { UpdateDatasetCollectionParams } from '@/pages/api/core/dataset/collection/update';
import type { import type {
@ -56,7 +56,6 @@ import type { UpdateDatasetDataProps } from '@fastgpt/global/core/dataset/contro
import type { DatasetFolderCreateBody } from '@/pages/api/core/dataset/folder/create'; import type { DatasetFolderCreateBody } from '@/pages/api/core/dataset/folder/create';
import type { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type'; import type { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
import type { GetScrollCollectionsProps } from '@/pages/api/core/dataset/collection/scrollList'; import type { GetScrollCollectionsProps } from '@/pages/api/core/dataset/collection/scrollList';
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api';
/* ======================== dataset ======================= */ /* ======================== dataset ======================= */
export const getDatasets = (data: GetDatasetListBody) => export const getDatasets = (data: GetDatasetListBody) =>
@ -198,6 +197,5 @@ export const getPreviewChunks = (data: PostPreviewFilesChunksProps) =>
POST<PreviewChunksResponse>('/core/dataset/file/getPreviewChunks', data); POST<PreviewChunksResponse>('/core/dataset/file/getPreviewChunks', data);
/* ================== read source ======================== */ /* ================== read source ======================== */
export const getCollectionSource = ( export const getCollectionSource = (data: readCollectionSourceBody) =>
data: { collectionId: string; isShare?: boolean } & AuthOutLinkProps POST<readCollectionSourceResponse>('/core/dataset/collection/read', data);
) => POST<readCollectionSourceResponse>('/core/dataset/collection/read', data);

View File

@ -1,20 +1,17 @@
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useSystemStore } from '@/web/common/system/useSystemStore';
import { getCollectionSource } from '@/web/core/dataset/api'; import { getCollectionSource } from '@/web/core/dataset/api';
import { getErrText } from '@fastgpt/global/common/error/utils'; import { getErrText } from '@fastgpt/global/common/error/utils';
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api';
import { useToast } from '@fastgpt/web/hooks/useToast'; import { useToast } from '@fastgpt/web/hooks/useToast';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { ShareChatAuthProps } from '@fastgpt/global/support/permission/chat';
export function getCollectionSourceAndOpen({ export function getCollectionSourceAndOpen({
collectionId, collectionId,
authProps, shareId,
isShare outLinkUid
}: { }: {
collectionId: string; collectionId: string;
authProps: AuthOutLinkProps; } & ShareChatAuthProps) {
isShare?: boolean;
}) {
const { toast } = useToast(); const { toast } = useToast();
const { t } = useTranslation(); const { t } = useTranslation();
const { setLoading } = useSystemStore(); const { setLoading } = useSystemStore();
@ -23,7 +20,7 @@ export function getCollectionSourceAndOpen({
try { try {
setLoading(true); setLoading(true);
const { value: url } = await getCollectionSource({ collectionId, isShare, ...authProps }); const { value: url } = await getCollectionSource({ collectionId, shareId, outLinkUid });
if (!url) { if (!url) {
throw new Error('No file found'); throw new Error('No file found');