update name

This commit is contained in:
heheer 2025-12-22 11:28:24 +08:00
parent 142f00139b
commit 98b780628f
No known key found for this signature in database
GPG Key ID: 37DCB43201661540
33 changed files with 413 additions and 255 deletions

View File

@ -1,6 +1,26 @@
import { z } from 'zod';
import { ObjectIdSchema } from '../../../../../common/type/mongo';
// Playground Visibility Config Fields
const PlaygroundVisibilityConfigFieldsSchema = z.object({
showRunningStatus: z.boolean().meta({
example: true,
description: '是否显示运行状态'
}),
showQuote: z.boolean().meta({
example: true,
description: '是否显示引用'
}),
showFullText: z.boolean().meta({
example: true,
description: '是否显示全文'
}),
canDownloadSource: z.boolean().meta({
example: true,
description: '是否可下载来源'
})
});
// Get Playground Visibility Config Parameters
export const GetPlaygroundVisibilityConfigParamsSchema = z.object({
appId: ObjectIdSchema.meta({
@ -13,51 +33,20 @@ export type GetPlaygroundVisibilityConfigParamsType = z.infer<
>;
// Playground Visibility Config Response
export const PlaygroundVisibilityConfigResponseSchema = z.object({
showNodeStatus: z.boolean().meta({
example: true,
description: '是否显示节点状态'
}),
responseDetail: z.boolean().meta({
example: true,
description: '是否显示响应详情'
}),
showFullText: z.boolean().meta({
example: true,
description: '是否显示全文'
}),
showRawSource: z.boolean().meta({
example: true,
description: '是否显示原始来源'
})
});
export const PlaygroundVisibilityConfigResponseSchema = PlaygroundVisibilityConfigFieldsSchema;
export type PlaygroundVisibilityConfigResponseType = z.infer<
typeof PlaygroundVisibilityConfigResponseSchema
>;
// Update Playground Visibility Config Parameters
export const UpdatePlaygroundVisibilityConfigParamsSchema = z.object({
appId: ObjectIdSchema.meta({
example: '68ad85a7463006c963799a05',
description: '应用 ID'
}),
showNodeStatus: z.boolean().meta({
example: true,
description: '是否显示节点状态'
}),
responseDetail: z.boolean().meta({
example: true,
description: '是否显示响应详情'
}),
showFullText: z.boolean().meta({
example: true,
description: '是否显示全文'
}),
showRawSource: z.boolean().meta({
example: true,
description: '是否显示原始来源'
export const UpdatePlaygroundVisibilityConfigParamsSchema = z
.object({
appId: ObjectIdSchema.meta({
example: '68ad85a7463006c963799a05',
description: '应用 ID'
})
})
});
.extend(PlaygroundVisibilityConfigFieldsSchema.shape);
export type UpdatePlaygroundVisibilityConfigParamsType = z.infer<
typeof UpdatePlaygroundVisibilityConfigParamsSchema
>;

View File

@ -64,14 +64,14 @@ export type OutLinkSchema<T extends OutlinkAppType = undefined> = {
lastTime: Date;
type: PublishChannelEnum;
// whether the response content is detailed
responseDetail: boolean;
// whether to hide the node status
showNodeStatus?: boolean;
// wheter to show the full text reader
// whether to show the quote
showQuote: boolean;
// whether to show the running status
showRunningStatus?: boolean;
// whether to show the full text reader
showFullText?: boolean;
// whether to show the complete quote
showRawSource?: boolean;
// whether can download source
canDownloadSource?: boolean;
// response when request
immediateResponse?: string;
@ -94,10 +94,10 @@ export type OutLinkSchema<T extends OutlinkAppType = undefined> = {
export type OutLinkEditType<T = undefined> = {
_id?: string;
name: string;
responseDetail?: OutLinkSchema<T>['responseDetail'];
showNodeStatus?: OutLinkSchema<T>['showNodeStatus'];
showQuote?: OutLinkSchema<T>['showQuote'];
showRunningStatus?: OutLinkSchema<T>['showRunningStatus'];
showFullText?: OutLinkSchema<T>['showFullText'];
showRawSource?: OutLinkSchema<T>['showRawSource'];
canDownloadSource?: OutLinkSchema<T>['canDownloadSource'];
// response when request
immediateResponse?: string;
// response when error or other situation
@ -109,10 +109,10 @@ export type OutLinkEditType<T = undefined> = {
};
export const PlaygroundVisibilityConfigSchema = z.object({
showNodeStatus: z.boolean(),
responseDetail: z.boolean(),
showRunningStatus: z.boolean(),
showQuote: z.boolean(),
showFullText: z.boolean(),
showRawSource: z.boolean()
canDownloadSource: z.boolean()
});
export type PlaygroundVisibilityConfigType = z.infer<typeof PlaygroundVisibilityConfigSchema>;

View File

@ -43,18 +43,18 @@ const OutLinkSchema = new Schema({
type: Date
},
responseDetail: {
showQuote: {
type: Boolean,
default: false
},
showNodeStatus: {
showRunningStatus: {
type: Boolean,
default: true
},
showFullText: {
type: Boolean
},
showRawSource: {
canDownloadSource: {
type: Boolean
},
limit: {

View File

@ -163,12 +163,11 @@ const ChatItem = (props: Props) => {
const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting);
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
const showNodeStatus = useContextSelector(ChatItemContext, (v) => v.showNodeStatus);
const showRunningStatus = useContextSelector(ChatItemContext, (v) => v.showRunningStatus);
const appId = useContextSelector(WorkflowRuntimeContext, (v) => v.appId);
const chatId = useContextSelector(WorkflowRuntimeContext, (v) => v.chatId);
const outLinkAuthData = useContextSelector(WorkflowRuntimeContext, (v) => v.outLinkAuthData);
const isShowReadRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource);
const isShowFullText = useContextSelector(ChatItemContext, (v) => v.isShowFullText);
const { totalQuoteList: quoteList = [] } = useMemo(
@ -323,7 +322,7 @@ const ChatItem = (props: Props) => {
<ChatAvatar src={avatar} type={type} />
{/* Workflow status */}
{!!chatStatusMap && statusBoxData && isLastChild && showNodeStatus && (
{!!chatStatusMap && statusBoxData && isLastChild && showRunningStatus && (
<Flex
alignItems={'center'}
px={3}

View File

@ -26,7 +26,7 @@ const QuoteList = React.memo(function QuoteList({
chatId: v.chatId,
...(v.outLinkAuthData || {})
}));
const showRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource);
const canDownloadSource = useContextSelector(ChatItemContext, (v) => v.canDownloadSource);
const showRouteToDatasetDetail = useContextSelector(
ChatItemContext,
(v) => v.showRouteToDatasetDetail
@ -87,7 +87,7 @@ const QuoteList = React.memo(function QuoteList({
>
<QuoteItem
quoteItem={item}
canViewSource={showRawSource}
canViewSource={canDownloadSource}
canEditData={showRouteToDatasetDetail}
canEditDataset={showRouteToDatasetDetail}
{...RawSourceBoxProps}

View File

@ -49,7 +49,8 @@ const ResponseTags = ({
const chatTime = historyItem.time || new Date();
const durationSeconds = historyItem.durationSeconds || 0;
const isResponseDetail = useContextSelector(ChatItemContext, (v) => v.isResponseDetail);
const isResponseDetail = useContextSelector(ChatItemContext, (v) => v.isShowQuote);
console.log('isResponseDetail', isResponseDetail);
const {
totalQuoteList: quoteList = [],
llmModuleAccount = 0,

View File

@ -186,7 +186,7 @@ const DingTalk = ({ appId }: { appId: string }) => {
name: item.name,
limit: item.limit,
app: item.app,
responseDetail: item.responseDetail,
showQuote: item.showQuote,
defaultResponse: item.defaultResponse,
immediateResponse: item.immediateResponse
});

View File

@ -185,7 +185,7 @@ const FeiShu = ({ appId }: { appId: string }) => {
name: item.name,
limit: item.limit,
app: item.app,
responseDetail: item.responseDetail,
showQuote: item.showQuote,
defaultResponse: item.defaultResponse,
immediateResponse: item.immediateResponse
});

View File

@ -140,7 +140,7 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => {
}`
: ''}
</Td>
<Td>{item.responseDetail ? '✔' : '✖'}</Td>
<Td>{item.showQuote ? '✔' : '✖'}</Td>
{feConfigs?.isPlus && (
<>
<Td>{item?.limit?.QPM || '-'}</Td>
@ -182,10 +182,10 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => {
setEditLinkData({
_id: item._id,
name: item.name,
responseDetail: item.responseDetail ?? false,
showRawSource: item.showRawSource ?? false,
showQuote: item.showQuote ?? false,
canDownloadSource: item.canDownloadSource ?? false,
showFullText: item.showFullText ?? true,
showNodeStatus: item.showNodeStatus ?? false,
showRunningStatus: item.showRunningStatus ?? false,
limit: item.limit
})
},
@ -281,9 +281,9 @@ function EditLinkModal({
defaultValues: defaultData
});
const responseDetail = watch('responseDetail');
const showQuote = watch('showQuote');
const showFullText = watch('showFullText');
const showRawSource = watch('showRawSource');
const canDownloadSource = watch('canDownloadSource');
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
@ -413,7 +413,7 @@ function EditLinkModal({
</Box>
<Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
<FormLabel>{t('publish:show_node')}</FormLabel>
<Switch {...register('showNodeStatus')} />
<Switch {...register('showRunningStatus')} />
</Flex>
<Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
<Flex alignItems={'center'}>
@ -424,15 +424,15 @@ function EditLinkModal({
></QuestionTip>
</Flex>
<Switch
{...register('responseDetail', {
{...register('showQuote', {
onChange(e) {
if (!e.target.checked) {
setValue('showFullText', false);
setValue('showRawSource', false);
setValue('canDownloadSource', false);
}
}
})}
isChecked={responseDetail}
isChecked={showQuote}
/>
</Flex>
<Flex alignItems={'center'} mt={4} justify={'space-between'} height={'36px'}>
@ -447,9 +447,9 @@ function EditLinkModal({
{...register('showFullText', {
onChange(e) {
if (!e.target.checked) {
setValue('showRawSource', false);
setValue('canDownloadSource', false);
} else {
setValue('responseDetail', true);
setValue('showQuote', true);
}
}
})}
@ -465,15 +465,15 @@ function EditLinkModal({
></QuestionTip>
</Flex>
<Switch
{...register('showRawSource', {
{...register('canDownloadSource', {
onChange(e) {
if (e.target.checked) {
setValue('showFullText', true);
setValue('responseDetail', true);
setValue('showQuote', true);
}
}
})}
isChecked={showRawSource}
isChecked={canDownloadSource}
/>
</Flex>
</Box>

View File

@ -188,7 +188,7 @@ const OffiAccount = ({ appId }: { appId: string }) => {
name: item.name,
limit: item.limit,
app: item.app,
responseDetail: item.responseDetail,
showQuote: item.showQuote,
defaultResponse: item.defaultResponse,
immediateResponse: item.immediateResponse
});

View File

@ -14,10 +14,10 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import { useCopyData } from '@fastgpt/web/hooks/useCopyData';
const defaultPlaygroundVisibilityForm: PlaygroundVisibilityConfigType = {
showNodeStatus: true,
responseDetail: true,
showRunningStatus: true,
showQuote: true,
showFullText: true,
showRawSource: true
canDownloadSource: true
};
const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
@ -28,9 +28,9 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
defaultValues: defaultPlaygroundVisibilityForm
});
const responseDetail = watch('responseDetail');
const showQuote = watch('showQuote');
const showFullText = watch('showFullText');
const showRawSource = watch('showRawSource');
const canDownloadSource = watch('canDownloadSource');
const playgroundLink = useMemo(() => {
if (typeof window !== 'undefined') {
@ -42,10 +42,10 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
useRequest2(() => getPlaygroundVisibilityConfig({ appId }), {
onSuccess: (data) => {
reset({
showNodeStatus: data.showNodeStatus,
responseDetail: data.responseDetail,
showRunningStatus: data.showRunningStatus,
showQuote: data.showQuote,
showFullText: data.showFullText,
showRawSource: data.showRawSource
canDownloadSource: data.canDownloadSource
});
},
manual: false
@ -110,7 +110,7 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
{t('publish:show_node')}
</FormLabel>
<Switch
{...register('showNodeStatus', {
{...register('showRunningStatus', {
onChange: autoSave
})}
/>
@ -123,16 +123,16 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
<QuestionTip ml={1} label={t('common:support.outlink.share.Response Quote tips')} />
</Flex>
<Switch
{...register('responseDetail', {
{...register('showQuote', {
onChange(e) {
if (!e.target.checked) {
setValue('showFullText', false);
setValue('showRawSource', false);
setValue('canDownloadSource', false);
}
autoSave();
}
})}
isChecked={responseDetail}
isChecked={showQuote}
/>
</Flex>
</Grid>
@ -147,9 +147,9 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
{...register('showFullText', {
onChange(e) {
if (!e.target.checked) {
setValue('showRawSource', false);
setValue('canDownloadSource', false);
} else {
setValue('responseDetail', true);
setValue('showQuote', true);
}
autoSave();
}
@ -165,16 +165,16 @@ const PlaygroundVisibilityConfig = ({ appId }: { appId: string }) => {
<QuestionTip ml={1} label={t('common:support.outlink.share.Download source tips')} />
</Flex>
<Switch
{...register('showRawSource', {
{...register('canDownloadSource', {
onChange(e) {
if (e.target.checked) {
setValue('showFullText', true);
setValue('responseDetail', true);
setValue('showQuote', true);
}
autoSave();
}
})}
isChecked={showRawSource}
isChecked={canDownloadSource}
/>
</Flex>
</Grid>

View File

@ -200,7 +200,7 @@ const Wecom = ({ appId }: { appId: string }) => {
name: item.name,
limit: item.limit,
app: item.app,
responseDetail: item.responseDetail,
showQuote: item.showQuote,
defaultResponse: item.defaultResponse,
immediateResponse: item.immediateResponse
});

View File

@ -39,7 +39,7 @@ const CollectionReader = ({
const router = useRouter();
const { userInfo } = useUserStore();
const isShowReadRawSource = useContextSelector(ChatItemContext, (v) => v.isShowReadRawSource);
const canDownloadSource = useContextSelector(ChatItemContext, (v) => v.canDownloadSource);
const { collectionId, datasetId, chatItemDataId, sourceId, sourceName, quoteId } = metadata;
const [quoteIndex, setQuoteIndex] = useState(0);
@ -179,7 +179,7 @@ const CollectionReader = ({
{sourceName || t('common:unknow_source')}
</Box>
<Box ml={3}>
{isShowReadRawSource && (
{canDownloadSource && (
<DownloadButton
canAccessRawData={true}
onDownload={handleDownload}

View File

@ -5,8 +5,8 @@ import type { S3MQJobData } from '@fastgpt/service/common/s3/mq';
import { addLog } from '@fastgpt/service/common/system/log';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { PublishChannelEnum } from '@fastgpt/global/support/outLink/constant';
import { connectionMongo } from '@fastgpt/service/common/mongo';
export type ResponseType = {
message: string;
@ -15,6 +15,10 @@ export type ResponseType = {
shareLinkMigration: {
totalRecords: number;
updatedRecords: number;
updateResults: Array<{
operation: string;
updated: number;
}>;
};
};
@ -22,14 +26,19 @@ export type ResponseType = {
* 4.14.5
* 1. S3
* 2. share OutLink showFullText
* 3.
* - showNodeStatus -> showRunningStatus
* - responseDetail -> showQuote
* - showRawSource -> canDownloadSource
*/
async function handler(
req: ApiRequestProps,
res: ApiResponseType<ResponseType>
): Promise<ResponseType> {
await authCert({ req, authRoot: true });
// 1. 处理失败的 S3 删除任务
/**
* 功能1: 重试所有失败的 S3
*/
async function retryFailedS3DeleteJobs(): Promise<{
retriedCount: number;
failedCount: number;
}> {
const queue = getQueue<S3MQJobData>(QueueNames.s3FileDelete);
const failedJobs = await queue.getFailed();
console.log(`Found ${failedJobs.length} failed S3 delete jobs`);
@ -68,45 +77,207 @@ async function handler(
100
);
// 2. 处理 share 类型的 OutLink 记录迁移
let shareLinkMigration = { totalRecords: 0, updatedRecords: 0 };
return {
retriedCount,
failedCount: failedJobs.length
};
}
/**
* 功能2和3: 处理 OutLink
* - showFullText
* -
*/
async function migrateOutLinkData(): Promise<{
totalRecords: number;
updatedRecords: number;
updateResults: Array<{
operation: string;
updated: number;
}>;
}> {
let totalUpdated = 0;
const updateResults: Array<{
operation: string;
updated: number;
}> = [];
// 获取 MongoDB 原生集合,绕过 Mongoose 的严格模式
const db = connectionMongo.connection.db;
if (!db) {
throw new Error('Database connection not established');
}
const outLinkCollection = db.collection('outlinks');
// 1. 为所有 share 类型的记录添加 showFullText 字段
const shareLinks = await outLinkCollection
.find({
type: PublishChannelEnum.share,
showFullText: { $exists: false } // 只查找没有 showFullText 字段的记录
})
.toArray();
if (shareLinks.length > 0) {
// 批量更新添加 showFullText 字段
const showFullTextOps = shareLinks.map((link: any) => ({
updateOne: {
filter: { _id: link._id },
update: { $set: { showFullText: link.showRawSource ?? true } }
}
}));
const showFullTextResult = await outLinkCollection.bulkWrite(showFullTextOps);
totalUpdated += showFullTextResult.modifiedCount;
updateResults.push({
operation: 'Add showFullText field',
updated: showFullTextResult.modifiedCount
});
console.log(`Added showFullText field to ${showFullTextResult.modifiedCount} share links`);
}
// 2. 重命名字段showNodeStatus -> showRunningStatus
const showNodeStatusLinks = await outLinkCollection
.find({
showNodeStatus: { $exists: true },
showRunningStatus: { $exists: false }
})
.toArray();
if (showNodeStatusLinks.length > 0) {
const renameNodeStatusOps = showNodeStatusLinks.map((link: any) => ({
updateOne: {
filter: { _id: link._id },
update: [
{
$set: { showRunningStatus: '$showNodeStatus' }
},
{
$unset: 'showNodeStatus'
}
]
}
}));
const renameNodeStatusResult = await outLinkCollection.bulkWrite(renameNodeStatusOps);
totalUpdated += renameNodeStatusResult.modifiedCount;
updateResults.push({
operation: 'Rename showNodeStatus to showRunningStatus',
updated: renameNodeStatusResult.modifiedCount
});
console.log(
`Renamed showNodeStatus to showRunningStatus for ${renameNodeStatusResult.modifiedCount} links`
);
}
// 3. 重命名字段responseDetail -> showQuote
const responseDetailLinks = await outLinkCollection
.find({
responseDetail: { $exists: true },
showQuote: { $exists: false }
})
.toArray();
if (responseDetailLinks.length > 0) {
const renameResponseDetailOps = responseDetailLinks.map((link: any) => ({
updateOne: {
filter: { _id: link._id },
update: [
{
$set: { showQuote: '$responseDetail' }
},
{
$unset: 'responseDetail'
}
]
}
}));
const renameResponseDetailResult = await outLinkCollection.bulkWrite(renameResponseDetailOps);
totalUpdated += renameResponseDetailResult.modifiedCount;
updateResults.push({
operation: 'Rename responseDetail to showQuote',
updated: renameResponseDetailResult.modifiedCount
});
console.log(
`Renamed responseDetail to showQuote for ${renameResponseDetailResult.modifiedCount} links`
);
}
// 4. 重命名字段showRawSource -> canDownloadSource
const showRawSourceLinks = await outLinkCollection
.find({
showRawSource: { $exists: true },
canDownloadSource: { $exists: false }
})
.toArray();
if (showRawSourceLinks.length > 0) {
const renameRawSourceOps = showRawSourceLinks.map((link: any) => ({
updateOne: {
filter: { _id: link._id },
update: [
{
$set: { canDownloadSource: '$showRawSource' }
},
{
$unset: 'showRawSource'
}
]
}
}));
const renameRawSourceResult = await outLinkCollection.bulkWrite(renameRawSourceOps);
totalUpdated += renameRawSourceResult.modifiedCount;
updateResults.push({
operation: 'Rename showRawSource to canDownloadSource',
updated: renameRawSourceResult.modifiedCount
});
console.log(
`Renamed showRawSource to canDownloadSource for ${renameRawSourceResult.modifiedCount} links`
);
}
return {
totalRecords: totalUpdated,
updatedRecords: totalUpdated,
updateResults
};
}
/**
*
*/
async function handler(
req: ApiRequestProps,
_res: ApiResponseType<ResponseType>
): Promise<ResponseType> {
await authCert({ req, authRoot: true });
// 执行功能1: 重试 S3 删除任务
const s3JobResult = await retryFailedS3DeleteJobs();
// 执行功能2&3: OutLink 数据迁移
let shareLinkMigration = {
totalRecords: 0,
updatedRecords: 0,
updateResults: [] as Array<{ operation: string; updated: number }>
};
try {
// 查找所有 share 类型且没有 showFullText 字段的记录
const shareLinks = await MongoOutLink.find({
type: PublishChannelEnum.share,
showFullText: { $exists: false }
}).lean();
shareLinkMigration.totalRecords = shareLinks.length;
if (shareLinks.length > 0) {
// 批量更新
const bulkOps = shareLinks.map((link) => ({
updateOne: {
filter: { _id: link._id },
update: { $set: { showFullText: link.showRawSource ?? true } }
}
}));
const result = await MongoOutLink.bulkWrite(bulkOps);
shareLinkMigration.updatedRecords = result.modifiedCount;
console.log(
`Migration completed: ${shareLinkMigration.updatedRecords}/${shareLinkMigration.totalRecords} share links updated`
);
} else {
console.log('No share link records need migration');
}
shareLinkMigration = await migrateOutLinkData();
} catch (error) {
console.error('Failed to migrate share links:', error);
console.error('Failed to migrate outLink data:', error);
// 即使迁移失败,也继续返回 S3 任务处理的结果
}
return {
message: `Completed S3 delete job retries and share link migration for v4.14.5`,
retriedCount,
failedCount: failedJobs.length,
message: `Completed v4.14.5 initialization: S3 job retries and outLink migration`,
retriedCount: s3JobResult.retriedCount,
failedCount: s3JobResult.failedCount,
shareLinkMigration
};
}

View File

@ -40,7 +40,7 @@ async function handler(
};
}
const [app, { responseDetail, showNodeStatus, authType }] = await Promise.all([
const [app, { showQuote, showRunningStatus, authType }] = await Promise.all([
MongoApp.findById(appId, 'type').lean(),
authChatCrud({
req,
@ -81,16 +81,16 @@ async function handler(
if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({
nodeRespones: item.responseData,
responseDetail
responseDetail: showQuote
});
if (showNodeStatus === false) {
if (showRunningStatus === false) {
item.value = item.value.filter((v) => v.type !== ChatItemValueTypeEnum.tool);
}
}
});
}
if (!responseDetail) {
if (!showQuote) {
histories.forEach((item) => {
if (item.obj === ChatRoleEnum.AI) {
item.value = removeAIResponseCite(item.value, false);
@ -99,7 +99,7 @@ async function handler(
}
return {
list: isPlugin ? histories : transformPreviewHistories(histories, responseDetail),
list: isPlugin ? histories : transformPreviewHistories(histories, showQuote),
total
};
}

View File

@ -50,7 +50,7 @@ async function handler(
};
}
const [app, { responseDetail, showNodeStatus, authType }] = await Promise.all([
const [app, { showQuote, showRunningStatus, authType }] = await Promise.all([
MongoApp.findById(appId, 'type').lean(),
authChatCrud({
req,
@ -93,16 +93,16 @@ async function handler(
if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({
nodeRespones: item.responseData,
responseDetail
responseDetail: showQuote
});
if (showNodeStatus === false) {
if (showRunningStatus === false) {
item.value = item.value.filter((v) => v.type !== ChatItemValueTypeEnum.tool);
}
}
});
}
if (!responseDetail) {
if (!showQuote) {
result.histories.forEach((item) => {
if (item.obj === ChatRoleEnum.AI) {
item.value = removeAIResponseCite(item.value, false);
@ -110,9 +110,7 @@ async function handler(
});
}
const list = isPlugin
? result.histories
: transformPreviewHistories(result.histories, responseDetail);
const list = isPlugin ? result.histories : transformPreviewHistories(result.histories, showQuote);
return {
list: list.map((item) => ({

View File

@ -27,7 +27,7 @@ async function handler(
return [];
}
const [{ responseDetail }, chatData, nodeResponses] = await Promise.all([
const [{ showQuote }, chatData, nodeResponses] = await Promise.all([
authChatCrud({
req,
authToken: true,
@ -57,7 +57,7 @@ async function handler(
const flowResponses = chatData.responseData?.length ? chatData.responseData : nodeResponses;
return req.query.shareId
? filterPublicNodeResponseData({
responseDetail,
responseDetail: showQuote,
nodeRespones: flowResponses
})
: flowResponses;

View File

@ -57,7 +57,7 @@ async function handler(
const limitedPageSize = Math.min(pageSize, 30);
const [collection, { chat, showRawSource, showFullText }, chatItem] = await Promise.all([
const [collection, { chat, showFullText }, chatItem] = await Promise.all([
getCollectionWithDataset(collectionId),
authChatCrud({
req,

View File

@ -39,7 +39,7 @@ async function handler(req: ApiRequestProps<GetQuoteProps>): Promise<GetQuotesRe
datasetDataIdList
} = req.body;
const [{ chat, responseDetail }, chatItem] = await Promise.all([
const [{ chat, showQuote }, chatItem] = await Promise.all([
authChatCrud({
req,
authToken: true,
@ -53,7 +53,7 @@ async function handler(req: ApiRequestProps<GetQuoteProps>): Promise<GetQuotesRe
MongoChatItem.findOne({ appId, chatId, dataId: chatItemDataId }, 'time').lean(),
authCollectionInChat({ appId, chatId, chatItemDataId, collectionIds: collectionIdList })
]);
if (!chat || !chatItem || !responseDetail) return Promise.reject(ChatErrEnum.unAuthChat);
if (!chat || !chatItem || !showQuote) return Promise.reject(ChatErrEnum.unAuthChat);
const list = await MongoDatasetData.find(
{ _id: { $in: datasetDataIdList }, collectionId: { $in: collectionIdList } },

View File

@ -67,7 +67,7 @@ async function handler(req: ApiRequestProps<ExportCollectionBody, {}>, res: Next
authCollectionInChat({ appId, chatId, chatItemDataId, collectionIds: [collectionId] })
]);
if (!authRes.showRawSource) {
if (!authRes.canDownloadSource) {
return Promise.reject(DatasetErrEnum.unAuthDatasetFile);
}

View File

@ -63,7 +63,7 @@ async function handler(
authCollectionInChat({ appId, chatId, chatItemDataId, collectionIds: [collectionId] })
]);
if (!authRes.showRawSource) {
if (!authRes.canDownloadSource) {
return Promise.reject(DatasetErrEnum.unAuthDatasetFile);
}

View File

@ -51,7 +51,7 @@ async function handler(req: ApiRequestProps<GetQuoteDataProps>): Promise<GetQuot
return Promise.reject(i18nT('common:data_not_found'));
}
const [collection, { responseDetail }] = await Promise.all([
const [collection, { showQuote }] = await Promise.all([
MongoDatasetCollection.findById(datasetData.collectionId).lean(),
authChatCrud({
req,
@ -73,7 +73,7 @@ async function handler(req: ApiRequestProps<GetQuoteDataProps>): Promise<GetQuot
if (!collection) {
return Promise.reject('Can not find the collection');
}
if (!responseDetail) {
if (!showQuote) {
return Promise.reject(ChatErrEnum.unAuthChat);
}

View File

@ -28,14 +28,14 @@ async function handler(
appId,
type: PublishChannelEnum.playground
},
'showNodeStatus responseDetail showFullText showRawSource'
'showRunningStatus showQuote showFullText canDownloadSource'
).lean();
return PlaygroundVisibilityConfigResponseSchema.parse({
showNodeStatus: existingConfig?.showNodeStatus ?? true,
responseDetail: existingConfig?.responseDetail ?? true,
showRunningStatus: existingConfig?.showRunningStatus ?? true,
showQuote: existingConfig?.showQuote ?? true,
showFullText: existingConfig?.showFullText ?? true,
showRawSource: existingConfig?.showRawSource ?? true
canDownloadSource: existingConfig?.canDownloadSource ?? true
});
}

View File

@ -10,7 +10,7 @@ import {
} from '@fastgpt/global/support/outLink/api.d';
async function handler(req: ApiRequestProps<UpdatePlaygroundVisibilityConfigBody, {}>) {
const { appId, showNodeStatus, responseDetail, showFullText, showRawSource } =
const { appId, showRunningStatus, showQuote, showFullText, canDownloadSource } =
UpdatePlaygroundVisibilityConfigBodySchema.parse(req.body);
const { teamId, tmbId } = await authApp({
@ -32,10 +32,10 @@ async function handler(req: ApiRequestProps<UpdatePlaygroundVisibilityConfigBody
$set: {
appId,
type: PublishChannelEnum.playground,
showNodeStatus: showNodeStatus ?? true,
responseDetail: responseDetail ?? true,
showRunningStatus: showRunningStatus ?? true,
showQuote: showQuote ?? true,
showFullText: showFullText ?? true,
showRawSource: showRawSource ?? true
canDownloadSource: canDownloadSource ?? true
}
},
{ upsert: true }

View File

@ -26,7 +26,7 @@ export type OutLinkUpdateResponse = string;
async function handler(
req: ApiRequestProps<OutLinkUpdateBody, OutLinkUpdateQuery>
): Promise<OutLinkUpdateResponse> {
const { _id, name, responseDetail, limit, app, showRawSource, showNodeStatus, showFullText } =
const { _id, name, showQuote, limit, app, canDownloadSource, showRunningStatus, showFullText } =
req.body;
if (!_id) {
@ -47,9 +47,9 @@ async function handler(
const doc = await MongoOutLink.findByIdAndUpdate(_id, {
name,
responseDetail,
showRawSource,
showNodeStatus,
showQuote,
canDownloadSource,
showRunningStatus,
showFullText,
limit,
app

View File

@ -91,8 +91,8 @@ type AuthResponseType = {
teamId: string;
tmbId: string;
app: AppSchema;
responseDetail?: boolean;
showNodeStatus?: boolean;
showQuote?: boolean;
showRunningStatus?: boolean;
authType: `${AuthUserTypeEnum}`;
apikey?: string;
responseAllData: boolean;
@ -157,13 +157,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
teamId,
tmbId,
app,
responseDetail,
showQuote,
authType,
sourceName,
apikey,
responseAllData,
outLinkUserId = customUid,
showNodeStatus
showRunningStatus
} = await (async () => {
// share chat
if (shareId && outLinkUid) {
@ -205,7 +205,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
pushTrack.teamChatQPM({ teamId });
retainDatasetCite = retainDatasetCite && !!responseDetail;
retainDatasetCite = retainDatasetCite && !!showQuote;
const isPlugin = app.type === AppTypeEnum.workflowTool;
// Check message type
@ -275,7 +275,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
detail,
streamResponse: stream,
id: chatId,
showNodeStatus
showNodeStatus: showRunningStatus
});
const saveChatId = chatId || getNanoid(24);
@ -388,7 +388,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
/* select fe response field */
const feResponseData = responseAllData
? flowResponses
: filterPublicNodeResponseData({ nodeRespones: flowResponses, responseDetail });
: filterPublicNodeResponseData({ nodeRespones: flowResponses, responseDetail: showQuote });
if (stream) {
workflowResponseWrite({
@ -508,7 +508,7 @@ const authShareChat = async ({
shareId: string;
chatId?: string;
}): Promise<AuthResponseType> => {
const { teamId, tmbId, appId, authType, responseDetail, showNodeStatus, uid, sourceName } =
const { teamId, tmbId, appId, authType, showQuote, showRunningStatus, uid, sourceName } =
await authOutLinkChatStart(data);
const app = await MongoApp.findById(appId).lean();
@ -530,9 +530,9 @@ const authShareChat = async ({
apikey: '',
authType,
responseAllData: false,
responseDetail,
showQuote,
outLinkUserId: uid,
showNodeStatus
showRunningStatus
};
};
const authTeamSpaceChat = async ({
@ -569,7 +569,7 @@ const authTeamSpaceChat = async ({
authType: AuthUserTypeEnum.outLink,
apikey: '',
responseAllData: false,
responseDetail: true,
showQuote: true,
outLinkUserId: uid
};
};
@ -651,7 +651,7 @@ const authHeaderRequest = async ({
authType,
sourceName,
responseAllData: true,
responseDetail: true
showQuote: true
};
};

View File

@ -92,8 +92,8 @@ type AuthResponseType = {
teamId: string;
tmbId: string;
app: AppSchema;
responseDetail?: boolean;
showNodeStatus?: boolean;
showQuote?: boolean;
showRunningStatus?: boolean;
authType: `${AuthUserTypeEnum}`;
apikey?: string;
responseAllData: boolean;
@ -158,13 +158,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
teamId,
tmbId,
app,
responseDetail,
showQuote,
authType,
sourceName,
apikey,
responseAllData,
outLinkUserId = customUid,
showNodeStatus
showRunningStatus
} = await (async () => {
// share chat
if (shareId && outLinkUid) {
@ -206,7 +206,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
pushTrack.teamChatQPM({ teamId });
retainDatasetCite = retainDatasetCite && !!responseDetail;
retainDatasetCite = retainDatasetCite && !!showQuote;
const isPlugin = app.type === AppTypeEnum.workflowTool;
// Check message type
@ -275,7 +275,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
detail,
streamResponse: stream,
id: chatId,
showNodeStatus
showNodeStatus: showRunningStatus
});
const saveChatId = chatId || getNanoid(24);
@ -321,7 +321,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
maxRunTimes: WORKFLOW_MAX_RUN_TIMES,
workflowStreamResponse: workflowResponseWrite,
responseAllData,
responseDetail
responseDetail: showQuote
});
}
return Promise.reject('您的工作流版本过低,请重新发布一次');
@ -390,7 +390,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
/* select fe response field */
const feResponseData = responseAllData
? flowResponses
: filterPublicNodeResponseData({ nodeRespones: flowResponses, responseDetail });
: filterPublicNodeResponseData({ nodeRespones: flowResponses, responseDetail: showQuote });
if (stream) {
workflowResponseWrite({
@ -503,7 +503,7 @@ const authShareChat = async ({
shareId: string;
chatId?: string;
}): Promise<AuthResponseType> => {
const { teamId, tmbId, appId, authType, responseDetail, showNodeStatus, uid, sourceName } =
const { teamId, tmbId, appId, authType, showQuote, showRunningStatus, uid, sourceName } =
await authOutLinkChatStart(data);
const app = await MongoApp.findById(appId).lean();
@ -525,9 +525,9 @@ const authShareChat = async ({
apikey: '',
authType,
responseAllData: false,
responseDetail,
showQuote,
outLinkUserId: uid,
showNodeStatus
showRunningStatus
};
};
const authTeamSpaceChat = async ({
@ -564,7 +564,7 @@ const authTeamSpaceChat = async ({
authType: AuthUserTypeEnum.outLink,
apikey: '',
responseAllData: false,
responseDetail: true,
showQuote: true,
outLinkUserId: uid
};
};
@ -646,7 +646,7 @@ const authHeaderRequest = async ({
authType,
sourceName,
responseAllData: true,
responseDetail: true
showQuote: true
};
};

View File

@ -94,10 +94,10 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
const Render = (props: {
appId: string;
isStandalone?: string;
showNodeStatus: boolean;
responseDetail: boolean;
showRunningStatus: boolean;
showQuote: boolean;
showFullText: boolean;
showRawSource: boolean;
canDownloadSource: boolean;
}) => {
const { appId, isStandalone } = props;
const { chatId } = useChatStore();
@ -148,9 +148,9 @@ const Render = (props: {
<ChatContextProvider params={chatHistoryProviderParams}>
<ChatItemContextProvider
showRouteToDatasetDetail={isStandalone !== '1'}
showNodeStatus={props.showNodeStatus}
isShowReadRawSource={props.showRawSource}
isResponseDetail={props.responseDetail}
showRunningStatus={props.showRunningStatus}
canDownloadSource={props.canDownloadSource}
isShowQuote={props.showQuote}
isShowFullText={props.showFullText}
>
<ChatRecordContextProvider params={chatRecordProviderParams}>
@ -176,7 +176,7 @@ export async function getServerSideProps(context: any) {
appId,
type: PublishChannelEnum.playground
},
'showNodeStatus responseDetail showFullText showRawSource'
'showRunningStatus showQuote showFullText canDownloadSource'
).lean();
return config;
@ -189,10 +189,10 @@ export async function getServerSideProps(context: any) {
return {
props: {
appId,
showNodeStatus: chatQuoteReaderConfig?.showNodeStatus ?? true,
responseDetail: chatQuoteReaderConfig?.responseDetail ?? true,
showRunningStatus: chatQuoteReaderConfig?.showRunningStatus ?? true,
showQuote: chatQuoteReaderConfig?.showQuote ?? true,
showFullText: chatQuoteReaderConfig?.showFullText ?? true,
showRawSource: chatQuoteReaderConfig?.showRawSource ?? true,
canDownloadSource: chatQuoteReaderConfig?.canDownloadSource ?? true,
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
}
};

View File

@ -53,10 +53,10 @@ type Props = {
shareId: string;
authToken: string;
customUid: string;
showRawSource: boolean;
responseDetail: boolean;
showFullText: boolean;
showNodeStatus: boolean;
canDownloadSource: boolean;
isShowQuote: boolean;
isShowFullText: boolean;
showRunningStatus: boolean;
};
const OutLink = (props: Props) => {
@ -95,7 +95,7 @@ const OutLink = (props: Props) => {
const setChatBoxData = useContextSelector(ChatItemContext, (v) => v.setChatBoxData);
const datasetCiteData = useContextSelector(ChatItemContext, (v) => v.datasetCiteData);
const setCiteModalData = useContextSelector(ChatItemContext, (v) => v.setCiteModalData);
const isResponseDetail = useContextSelector(ChatItemContext, (v) => v.isResponseDetail);
const canDownloadSource = useContextSelector(ChatItemContext, (v) => v.canDownloadSource);
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount);
@ -175,7 +175,7 @@ const OutLink = (props: Props) => {
responseChatItemId,
chatId: completionChatId,
...outLinkAuthData,
retainDatasetCite: isResponseDetail
retainDatasetCite: canDownloadSource
},
onMessage: generatingMessage,
abortCtrl: controller
@ -213,7 +213,7 @@ const OutLink = (props: Props) => {
chatId,
customVariables,
outLinkAuthData,
isResponseDetail,
canDownloadSource,
onUpdateHistoryTitle,
setChatBoxData,
forbidLoadChat,
@ -388,10 +388,10 @@ const Render = (props: Props) => {
<ChatContextProvider params={chatHistoryProviderParams}>
<ChatItemContextProvider
showRouteToDatasetDetail={false}
isShowReadRawSource={props.showRawSource}
isResponseDetail={props.responseDetail}
isShowFullText={props.showFullText}
showNodeStatus={props.showNodeStatus}
canDownloadSource={props.canDownloadSource}
isShowQuote={props.isShowQuote}
isShowFullText={props.isShowFullText}
showRunningStatus={props.showRunningStatus}
>
<ChatRecordContextProvider params={chatRecordProviderParams}>
<OutLink {...props} />
@ -416,7 +416,7 @@ export async function getServerSideProps(context: any) {
{
shareId
},
'appId showRawSource showNodeStatus responseDetail showFullText'
'appId canDownloadSource showQuote showFullText showRunningStatus'
)
.populate<{ associatedApp: AppSchema }>('associatedApp', 'name avatar intro')
.lean();
@ -432,10 +432,10 @@ export async function getServerSideProps(context: any) {
appName: app?.associatedApp?.name ?? 'AI',
appAvatar: app?.associatedApp?.avatar ?? '',
appIntro: app?.associatedApp?.intro ?? 'AI',
showRawSource: app?.showRawSource ?? false,
responseDetail: app?.responseDetail ?? false,
showFullText: app?.showFullText ?? false,
showNodeStatus: app?.showNodeStatus ?? false,
canDownloadSource: app?.canDownloadSource ?? false,
isShowQuote: app?.showQuote ?? false,
isShowFullText: app?.showFullText ?? false,
showRunningStatus: app?.showRunningStatus ?? false,
shareId: shareId ?? '',
authToken: authToken ?? '',
customUid,

View File

@ -24,10 +24,10 @@ import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
Chat没有读写的权限之分
*/
export const defaultResponseShow = {
responseDetail: true,
showNodeStatus: true,
showQuote: true,
showRunningStatus: true,
showFullText: true,
showRawSource: true
canDownloadSource: true
};
type AuthChatCommonProps = {
appId: string;
@ -55,10 +55,10 @@ export async function authChatCrud({
tmbId: string;
uid: string;
chat?: ChatSchemaType;
responseDetail: boolean;
showNodeStatus: boolean;
showQuote: boolean;
showRunningStatus: boolean;
showFullText: boolean;
showRawSource: boolean;
canDownloadSource: boolean;
authType?: `${AuthUserTypeEnum}`;
}> {
if (!appId) return Promise.reject(ChatErrEnum.unAuthChat);
@ -111,10 +111,10 @@ export async function authChatCrud({
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showQuote: outLinkConfig.showQuote,
showRunningStatus: outLinkConfig.showRunningStatus ?? true,
showFullText: outLinkConfig.showFullText ?? false,
showRawSource: outLinkConfig.showRawSource ?? false,
canDownloadSource: outLinkConfig.canDownloadSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}
@ -126,10 +126,10 @@ export async function authChatCrud({
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showQuote: outLinkConfig.showQuote,
showRunningStatus: outLinkConfig.showRunningStatus ?? true,
showFullText: outLinkConfig.showFullText ?? false,
showRawSource: outLinkConfig.showRawSource ?? false,
canDownloadSource: outLinkConfig.canDownloadSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}
@ -139,10 +139,10 @@ export async function authChatCrud({
tmbId: String(outLinkConfig.tmbId),
chat,
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showQuote: outLinkConfig.showQuote,
showRunningStatus: outLinkConfig.showRunningStatus ?? true,
showFullText: outLinkConfig.showFullText ?? false,
showRawSource: outLinkConfig.showRawSource ?? false,
canDownloadSource: outLinkConfig.canDownloadSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}

View File

@ -63,10 +63,10 @@ export async function authOutLinkChatStart({
teamId: outLinkConfig.teamId,
tmbId: outLinkConfig.tmbId,
authType: AuthUserTypeEnum.token,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus,
showQuote: outLinkConfig.showQuote,
showRunningStatus: outLinkConfig.showRunningStatus,
showFullText: outLinkConfig.showFullText,
showRawSource: outLinkConfig.showRawSource,
canDownloadSource: outLinkConfig.canDownloadSource,
appId,
uid
};

View File

@ -26,10 +26,10 @@ export const defaultApp: AppDetailType = {
export const defaultOutLinkForm: OutLinkEditType = {
name: '',
showNodeStatus: true,
responseDetail: false,
showRunningStatus: true,
showQuote: false,
showFullText: false,
showRawSource: false,
canDownloadSource: false,
limit: {
QPM: 100,
maxUsagePoints: -1

View File

@ -13,10 +13,10 @@ import { type OutLinkChatAuthProps } from '@fastgpt/global/support/permission/ch
type ContextProps = {
showRouteToDatasetDetail: boolean;
isShowReadRawSource: boolean;
isResponseDetail: boolean;
canDownloadSource: boolean;
isShowQuote: boolean;
isShowFullText: boolean;
showNodeStatus: boolean;
showRunningStatus: boolean;
};
type ChatBoxDataType = {
chatId?: string;
@ -120,10 +120,10 @@ export const ChatItemContext = createContext<ChatItemContextType>({
const ChatItemContextProvider = ({
children,
showRouteToDatasetDetail,
isShowReadRawSource,
isResponseDetail,
canDownloadSource,
isShowQuote,
isShowFullText,
showNodeStatus
showRunningStatus
}: {
children: ReactNode;
} & ContextProps) => {
@ -196,10 +196,10 @@ const ChatItemContextProvider = ({
resetVariables,
clearChatRecords,
showRouteToDatasetDetail,
isShowReadRawSource,
isResponseDetail,
canDownloadSource,
isShowQuote,
isShowFullText,
showNodeStatus,
showRunningStatus,
datasetCiteData,
setCiteModalData,
@ -214,10 +214,10 @@ const ChatItemContextProvider = ({
resetVariables,
clearChatRecords,
showRouteToDatasetDetail,
isShowReadRawSource,
isResponseDetail,
canDownloadSource,
isShowQuote,
showRunningStatus,
isShowFullText,
showNodeStatus,
datasetCiteData,
setCiteModalData,
isVariableVisible,