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

@@ -1,32 +1,14 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
import { startQueue } from '@/service/utils/tools';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { userId } = await authCert({ req, authToken: true });
await unlockTask(userId);
await authCert({ req, authToken: true });
startQueue();
} catch (error) {}
jsonRes(res);
}
async function unlockTask(userId: string) {
try {
await MongoDatasetTraining.updateMany(
{
userId
},
{
lockTime: new Date('2000/1/1')
}
);
startQueue();
} catch (error) {
unlockTask(userId);
}
}

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 })
}
);

View File

@@ -1,51 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import type { InitShareChatResponse } from '@fastgpt/global/support/outLink/api.d';
import { HUMAN_ICON } from '@fastgpt/global/core/chat/constants';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { authShareChatInit } from '@/service/support/outLink/auth';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { authOutLinkValid } from '@fastgpt/service/support/permission/auth/outLink';
/* init share chat window */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
let { shareId, authToken } = req.query as {
shareId: string;
authToken?: string;
};
// get shareChat
const { app, shareChat } = await authOutLinkValid({ shareId });
// 校验使用权限
const [user] = await Promise.all([
MongoUser.findById(shareChat.userId, 'avatar'),
authShareChatInit({
authToken,
tokenUrl: shareChat.limit?.hookUrl
})
]);
jsonRes<InitShareChatResponse>(res, {
data: {
userAvatar: user?.avatar || HUMAN_ICON,
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
});
}
}

View File

@@ -3,7 +3,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { createJWT, setCookie } from '@fastgpt/service/support/permission/controller';
import { connectToDatabase } from '@/service/mongo';
import { getUserDetail } from '@/service/support/user/controller';
import { getUserDetail } from '@fastgpt/service/support/user/controller';
import type { PostLoginProps } from '@fastgpt/global/support/user/api.d';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {

View File

@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { connectToDatabase } from '@/service/mongo';
import { getUserDetail } from '@/service/support/user/controller';
import { getUserDetail } from '@fastgpt/service/support/user/controller';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { authCert, authCertAndShareId } from '@fastgpt/service/support/permission/auth/common';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { withNextCors } from '@fastgpt/service/common/middle/cors';
import { getUploadModel } from '@fastgpt/service/common/file/upload/multer';
import fs from 'fs';

View File

@@ -10,11 +10,11 @@ import { dispatchModules } from '@/service/moduleDispatch';
import type { ChatCompletionCreateParams } from '@fastgpt/global/core/ai/type.d';
import type { ChatMessageItemType } from '@fastgpt/global/core/ai/type.d';
import { gptMessage2ChatType, textAdaptGptResponse } from '@/utils/adapt';
import { getChatHistory } from './getHistory';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { saveChat } from '@/service/utils/chat/saveChat';
import { responseWrite } from '@fastgpt/service/common/response';
import { pushChatBill } from '@/service/support/wallet/bill/push';
import { authOutLinkChat } from '@/service/support/permission/auth/outLink';
import { authOutLinkChatStart } from '@/service/support/permission/auth/outLink';
import { pushResult2Remote, updateOutLinkUsage } from '@fastgpt/service/support/outLink/tools';
import requestIp from 'request-ip';
import { getBillSourceByAuthType } from '@fastgpt/global/support/wallet/bill/tools';
@@ -22,9 +22,10 @@ import { getBillSourceByAuthType } from '@fastgpt/global/support/wallet/bill/too
import { selectShareResponse } from '@/utils/service/core/chat';
import { updateApiKeyUsage } from '@fastgpt/service/support/openapi/tools';
import { connectToDatabase } from '@/service/mongo';
import { getUserAndAuthBalance } from '@/service/support/permission/auth/user';
import { getUserAndAuthBalance } from '@fastgpt/service/support/user/controller';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { autChatCrud } from '@/service/support/permission/auth/chat';
type FastGptWebChatProps = {
chatId?: string; // undefined: nonuse history, '': new chat, 'xxxxx': use history
@@ -32,7 +33,7 @@ type FastGptWebChatProps = {
};
type FastGptShareChatProps = {
shareId?: string;
authToken?: string;
outLinkUid?: string;
};
export type Props = ChatCompletionCreateParams &
FastGptWebChatProps &
@@ -56,11 +57,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
res.end();
});
let {
const {
chatId,
appId,
shareId,
authToken,
outLinkUid,
stream = false,
detail = false,
messages = [],
@@ -93,22 +94,29 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
throw new Error('Question is empty');
}
/* auth app permission */
const { user, app, responseDetail, authType, apikey, canWrite } = await (async () => {
if (shareId) {
const { user, app, authType, responseDetail } = await authOutLinkChat({
/* auth app permission */
const { user, app, responseDetail, authType, apikey, canWrite, uid } = await (async () => {
if (shareId && outLinkUid) {
const { user, appId, authType, responseDetail, uid } = await authOutLinkChatStart({
shareId,
ip: requestIp.getClientIp(req),
authToken,
outLinkUid,
question: question.value
});
const app = await MongoApp.findById(appId);
if (!app) {
return Promise.reject('app is empty');
}
return {
user,
app,
responseDetail,
apikey: '',
authType,
canWrite: false
canWrite: false,
uid
};
}
@@ -146,11 +154,10 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
};
}
// token auth
if (!appId) {
return Promise.reject('appId is empty');
}
// token
const { app, canWrite } = await authApp({
req,
authToken: true,
@@ -168,12 +175,19 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
};
})();
// auth app, get history
const { history } = await getChatHistory({ chatId, tmbId: user.team.tmbId });
// auth chat permission
await autChatCrud({
req,
authToken: true,
authApiKey: true,
chatId,
shareId,
outLinkUid,
per: 'w'
});
const isAppOwner = !shareId && String(user.team.tmbId) === String(app.tmbId);
/* format prompts */
// get and concat history
const { history } = await getChatItems({ chatId, limit: 30, field: `dataId obj value` });
const concatHistory = history.concat(chatMessages);
/* start flow controller */
@@ -202,8 +216,9 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
teamId: user.team.teamId,
tmbId: user.team.tmbId,
variables,
updateUseTime: isAppOwner, // owner update use time
updateUseTime: !shareId && String(user.team.tmbId) === String(app.tmbId), // owner update use time
shareId,
outLinkUid: uid,
source: (() => {
if (shareId) {
return ChatSourceEnum.share;
@@ -281,7 +296,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
});
if (shareId) {
pushResult2Remote({ authToken, shareId, responseData });
pushResult2Remote({ outLinkUid, shareId, responseData });
updateOutLinkUsage({
shareId,
total

View File

@@ -1,73 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { connectToDatabase } from '@/service/mongo';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { Types } from '@fastgpt/service/common/mongo';
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
export type Props = {
appId?: string;
chatId?: string;
limit?: number;
};
export type Response = { history: ChatItemType[] };
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { tmbId } = await authCert({ req, authToken: true });
const { chatId, limit } = req.body as Props;
jsonRes<Response>(res, {
data: await getChatHistory({
chatId,
tmbId,
limit
})
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}
export async function getChatHistory({
chatId,
tmbId,
limit = 30
}: Props & { tmbId: string }): Promise<Response> {
if (!chatId) {
return { history: [] };
}
const history = await MongoChatItem.aggregate([
{
$match: {
chatId,
tmbId: new Types.ObjectId(tmbId)
}
},
{
$sort: {
_id: -1
}
},
{
$limit: limit
},
{
$project: {
dataId: 1,
obj: 1,
value: 1
}
}
]);
history.reverse();
return { history };
}