4.6.4-alpha (#569)

This commit is contained in:
Archer
2023-12-07 13:43:08 +08:00
committed by GitHub
parent 71afe71192
commit e01c38efe0
80 changed files with 1401 additions and 1109 deletions

View File

@@ -5,6 +5,7 @@ import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
/* 获取我的模型 */
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
@@ -20,6 +21,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
await authApp({ req, authToken: true, appId, per: 'owner' });
// 删除对应的聊天
await MongoChatItem.deleteMany({
appId
});
await MongoChat.deleteMany({
appId
});

View File

@@ -381,7 +381,7 @@ function datasetTemplate({
key: 'similarity',
value: 0.4,
type: FlowNodeInputTypeEnum.slider,
label: '相度',
label: '相度',
connected: true
},
{

View File

@@ -289,7 +289,7 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
key: 'similarity',
value: formData.dataset.similarity,
type: FlowNodeInputTypeEnum.slider,
label: '相度',
label: '相度',
connected: false
},
{

View File

@@ -8,8 +8,9 @@ import { pushChatBill } from '@/service/support/wallet/bill/push';
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { authUser } from '@/service/support/permission/auth/user';
import { dispatchModules } from '@/service/moduleDispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserAndAuthBalance } from '@fastgpt/service/support/user/controller';
export type Props = {
history: ChatItemType[];
@@ -40,15 +41,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
/* user auth */
const [{ teamId, tmbId }, { user }] = await Promise.all([
const [_, { teamId, tmbId }] = await Promise.all([
authApp({ req, authToken: true, appId, per: 'r' }),
authUser({
authCert({
req,
authToken: true,
minBalance: 0
authToken: true
})
]);
// auth balance
const user = await getUserAndAuthBalance({
tmbId,
minBalance: 0
});
/* start process */
const { responseData } = await dispatchModules({
res,

View File

@@ -0,0 +1,58 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { ClearHistoriesProps } from '@/global/core/chat/api';
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
/* clear chat history */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, shareId, outLinkUid } = req.query as ClearHistoriesProps;
const match = await (async () => {
if (shareId && outLinkUid) {
const { uid } = await authOutLink({ shareId, outLinkUid });
return {
shareId,
outLinkUid: uid
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
return {
appId,
tmbId,
source: ChatSourceEnum.online
};
}
return Promise.reject('Param are error');
})();
console.log(match);
// find chatIds
const list = await MongoChat.find(match, 'chatId').lean();
const idList = list.map((item) => item.chatId);
await MongoChatItem.deleteMany({
chatId: { $in: idList }
});
await MongoChat.deleteMany({
chatId: { $in: idList }
});
jsonRes(res);
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -0,0 +1,38 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { DelHistoryProps } from '@/global/core/chat/api';
import { autChatCrud } from '@/service/support/permission/auth/chat';
/* clear chat history */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { chatId, shareId, outLinkUid } = req.query as DelHistoryProps;
await autChatCrud({
req,
authToken: true,
chatId,
shareId,
outLinkUid,
per: 'w'
});
await MongoChatItem.deleteMany({
chatId
});
await MongoChat.findOneAndRemove({
chatId
});
jsonRes(res);
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,54 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
type Props = {
chatId?: string;
appId?: string;
};
/* clear chat history */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { chatId, appId } = req.query as Props;
const { tmbId } = await authCert({ req, authToken: true });
if (chatId) {
await MongoChatItem.deleteMany({
chatId,
tmbId
});
await MongoChat.findOneAndRemove({
chatId,
tmbId
});
}
if (appId) {
const chats = await MongoChat.find({
appId,
tmbId,
source: ChatSourceEnum.online
}).select('_id');
const chatIds = chats.map((chat) => chat._id);
await MongoChatItem.deleteMany({
chatId: { $in: chatIds }
});
await MongoChat.deleteMany({
_id: { $in: chatIds }
});
}
jsonRes(res);
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import type { AdminUpdateFeedbackParams } from '@fastgpt/global/core/chat/api.d';
import type { AdminUpdateFeedbackParams } from '@/global/core/chat/api.d';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
/* 初始化我的聊天框,需要身份验证 */

View File

@@ -0,0 +1,62 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { getHistoriesProps } from '@/global/core/chat/api';
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, shareId, outLinkUid } = req.body as getHistoriesProps;
const limit = shareId && outLinkUid ? 20 : 30;
const match = await (async () => {
if (shareId && outLinkUid) {
const { uid } = await authOutLink({ shareId, outLinkUid });
return {
shareId,
outLinkUid: uid,
source: ChatSourceEnum.share,
updateTime: {
$gte: new Date(new Date().setDate(new Date().getDate() - 30))
}
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
return {
appId,
tmbId,
source: ChatSourceEnum.online
};
}
return Promise.reject('Params are error');
})();
const data = await MongoChat.find(match, 'chatId title top customTitle appId updateTime')
.sort({ top: -1, updateTime: -1 })
.limit(limit);
jsonRes<ChatHistoryItemType[]>(res, {
data: data.map((item) => ({
chatId: item.chatId,
updateTime: item.updateTime,
appId: item.appId,
customTitle: item.customTitle,
title: item.title,
top: item.top
}))
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,24 +1,20 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import type { InitChatResponse } from '@fastgpt/global/core/chat/api.d';
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { authChat } from '@fastgpt/service/support/permission/auth/chat';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import type { InitChatProps, InitChatResponse } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
/* 初始化我的聊天框,需要身份验证 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
let { appId, chatId } = req.query as {
appId: string;
chatId: '' | string;
};
let { appId, chatId } = req.query as InitChatProps;
if (!appId) {
return jsonRes(res, {
@@ -27,57 +23,44 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
}
// 校验使用权限
const [{ app }, autChatResult] = await Promise.all([
// auth app permission
const [{ app, tmbId }, chat] = await Promise.all([
authApp({
req,
authToken: true,
appId,
per: 'r'
}),
chatId
? authChat({
req,
authToken: true,
chatId,
per: 'r'
})
: undefined
chatId ? MongoChat.findOne({ chatId }) : undefined
]);
// get app and history
const { history = [] }: { history?: ChatItemType[] } = await (async () => {
if (chatId) {
// auth chatId
const history = await MongoChatItem.find(
{
chatId
},
`dataId obj value adminFeedback userFeedback ${ModuleOutputKeyEnum.responseData}`
)
.sort({ _id: -1 })
.limit(30);
// auth chat permission
if (!app.canWrite && String(tmbId) !== String(chat?.tmbId)) {
throw new Error(ChatErrEnum.unAuthChat);
}
history.reverse();
return { history };
}
return {};
})();
// get app and history
const { history } = await getChatItems({
chatId,
limit: 30,
field: `dataId obj value adminFeedback userFeedback ${ModuleOutputKeyEnum.responseData}`
});
jsonRes<InitChatResponse>(res, {
data: {
chatId,
appId,
title: chat?.title || '新对话',
userAvatar: undefined,
variables: chat?.variables || {},
history,
app: {
userGuideModule: getGuideModule(app.modules),
chatModels: getChatModelNameListByModules(app.modules),
name: app.name,
avatar: app.avatar,
intro: app.intro
},
title: autChatResult?.chat?.title || '新对话',
variables: autChatResult?.chat?.variables || {},
history
}
}
});
} catch (err) {

View File

@@ -0,0 +1,42 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
/* clear chat history */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { outLinkUid, chatIds } = req.body as {
outLinkUid: string;
chatIds: string[];
};
if (!outLinkUid) {
throw new Error('shareId or outLinkUid is required');
}
const sliceIds = chatIds.slice(0, 50);
await MongoChat.updateMany(
{
chatId: { $in: sliceIds },
source: ChatSourceEnum.share,
outLinkUid: { $exists: false }
},
{
$set: {
outLinkUid
}
}
);
jsonRes(res);
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -2,14 +2,22 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { authChat } from '@fastgpt/service/support/permission/auth/chat';
import { autChatCrud } from '@/service/support/permission/auth/chat';
import type { DeleteChatItemProps } from '@/global/core/chat/api.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { chatId, contentId } = req.query as { chatId: string; contentId: string };
const { chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps;
await authChat({ req, authToken: true, chatId, per: 'w' });
await autChatCrud({
req,
authToken: true,
chatId,
shareId,
outLinkUid,
per: 'w'
});
await MongoChatItem.deleteOne({
dataId: contentId,

View File

@@ -1,43 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
/* 获取历史记录 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId } = req.body as { appId: string };
const { tmbId } = await authApp({ req, authToken: true, appId, per: 'r' });
const data = await MongoChat.find(
{
appId,
tmbId,
source: ChatSourceEnum.online
},
'chatId title top customTitle appId updateTime'
)
.sort({ top: -1, updateTime: -1 })
.limit(20);
jsonRes<ChatHistoryItemType[]>(res, {
data: data.map((item) => ({
chatId: item.chatId,
updateTime: item.updateTime,
appId: item.appId,
customTitle: item.customTitle,
title: item.title,
top: item.top
}))
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -0,0 +1,85 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import type { InitChatResponse, InitOutLinkChatProps } from '@/global/core/chat/api.d';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { selectShareResponse } from '@/utils/service/core/chat';
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
let { chatId, shareId, outLinkUid } = req.query as InitOutLinkChatProps;
// auth link permission
const { shareChat, uid, appId } = await authOutLink({ shareId, outLinkUid });
// auth app permission
const [tmb, chat, app] = await Promise.all([
MongoTeamMember.findById(shareChat.tmbId, '_id userId').populate('userId', 'avatar').lean(),
MongoChat.findOne({ chatId, shareId }).lean(),
MongoApp.findById(appId).lean()
]);
if (!app) {
throw new Error(AppErrEnum.unExist);
}
// auth chat permission
if (chat && chat.outLinkUid !== uid) {
throw new Error(ChatErrEnum.unAuthChat);
}
const { history } = await getChatItems({
chatId,
limit: 30,
field: `dataId obj value userFeedback ${
shareChat.responseDetail ? `adminFeedback ${ModuleOutputKeyEnum.responseData}` : ''
} `
});
// pick share response field
history.forEach((item) => {
item.responseData = selectShareResponse({ responseData: item.responseData });
});
jsonRes<InitChatResponse>(res, {
data: {
chatId,
appId: app._id,
title: chat?.title || '新对话',
//@ts-ignore
userAvatar: tmb?.userId?.avatar,
variables: chat?.variables || {},
history,
app: {
userGuideModule: getGuideModule(app.modules),
chatModels: getChatModelNameListByModules(app.modules),
name: app.name,
avatar: app.avatar,
intro: app.intro
}
}
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}
export const config = {
api: {
responseLimit: '10mb'
}
};

View File

@@ -1,17 +1,24 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { UpdateHistoryProps } from '@fastgpt/global/core/chat/api.d';
import { UpdateHistoryProps } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { authChat } from '@fastgpt/service/support/permission/auth/chat';
import { autChatCrud } from '@/service/support/permission/auth/chat';
/* 更新聊天标题 */
/* update chat top, custom title */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { chatId, customTitle, top } = req.body as UpdateHistoryProps;
const { chatId, shareId, outLinkUid, customTitle, top } = req.body as UpdateHistoryProps;
await authChat({ req, authToken: true, chatId });
await autChatCrud({
req,
authToken: true,
chatId,
shareId,
outLinkUid,
per: 'w'
});
await MongoChat.findOneAndUpdate(
{ chatId },

View File

@@ -8,7 +8,7 @@ import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { id, parentId, name, avatar, tags, permission, agentModel, websiteConfig, status } =
const { id, parentId, name, avatar, intro, permission, agentModel, websiteConfig, status } =
req.body as DatasetUpdateBody;
if (!id) {
@@ -26,11 +26,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...(parentId !== undefined && { parentId: parentId || null }),
...(name && { name }),
...(avatar && { avatar }),
...(tags && { tags }),
...(permission && { permission }),
...(agentModel && { agentModel: agentModel.model }),
...(websiteConfig && { websiteConfig }),
...(status && { status })
...(status && { status }),
...(intro && { intro })
}
);