V4.8.14 dev (#3234)

* feat: rewrite chat context (#3176)

* feat: add app auto execute (#3115)

* feat: add app auto execute

* auto exec configtion

* chatting animation

* change icon

* fix

* fix

* fix link

* feat: add chat context to all chatbox

* perf: loading ui

---------

Co-authored-by: heheer <heheer@sealos.io>

* app auto exec (#3179)

* add chat records loaded state (#3184)

* perf: chat store reset storage (#3186)

* perf: chat store reset storage

* perf: auto exec code

* chore: workflow ui (#3175)

* chore: workflow ui

* fix

* change icon color config

* change popover to mymenu

* 4.8.14 test (#3189)

* update doc

* fix: token check

* perf: icon button

* update doc

* feat: share page support configuration Whether to allow the original view (#3194)

* update doc

* perf: fix index (#3206)

* perf: i18n

* perf: Add service entry (#3226)

* 4.8.14 test (#3228)

* fix: ai log

* fix: text splitter

* fix: reference unselect & user form description & simple to advance (#3229)

* fix: reference unselect & user form description & simple to advance

* change abort position

* perf

* perf: code (#3232)

* perf: code

* update doc

* fix: create btn permission (#3233)

* update doc

* fix: refresh chatbox listener

* perf: check invalid reference

* perf: check invalid reference

* update doc

* fix: ui props

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2024-11-26 12:02:58 +08:00
committed by GitHub
parent 7e1d31b5a9
commit 8aa6b53760
221 changed files with 3831 additions and 2737 deletions

View File

@@ -33,7 +33,7 @@ export const readConfigData = (name: string) => {
};
/* Init global variables */
export function initGlobal() {
export function initGlobalVariables() {
if (global.communityPlugins) return;
global.communityPlugins = [];

View File

@@ -67,7 +67,7 @@ export const getSystemPluginCb = async (refresh = false) => {
try {
global.systemPluginCb = {};
await getSystemPlugins();
await getSystemPlugins(refresh);
global.systemPluginCb = FastGPTProUrl ? await getCommercialCb() : await getCommunityCb();
return global.systemPluginCb;
} catch (error) {

View File

@@ -1,6 +1,5 @@
import { connectToDatabase } from '../mongo';
import { NextEntry } from '@fastgpt/service/common/middle/entry';
export const NextAPI = NextEntry({
beforeCallback: [connectToDatabase()]
beforeCallback: []
});

View File

@@ -4,51 +4,17 @@ import { connectMongo } from '@fastgpt/service/common/mongo/init';
import { hashStr } from '@fastgpt/global/common/string/tools';
import { createDefaultTeam } from '@fastgpt/service/support/user/team/controller';
import { exit } from 'process';
import { initVectorStore } from '@fastgpt/service/common/vectorStore/controller';
import { startCron } from './common/system/cron';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { initGlobal, getInitConfig } from './common/system';
import { startMongoWatch } from './common/system/volumnMongoWatch';
import { startTrainingQueue } from './core/dataset/training/utils';
import { systemStartCb } from '@fastgpt/service/common/system/tools';
import { addLog } from '@fastgpt/service/common/system/log';
import { getSystemPluginCb } from './core/app/plugin';
/**
* This function is equivalent to the entry to the service
* connect MongoDB and init data
*/
export function connectToDatabase() {
if (!global.systemLoadedGlobalVariables) {
global.systemLoadedGlobalVariables = true;
initGlobal();
}
return connectMongo().then(async () => {
if (global.systemLoadedGlobalConfig) return;
global.systemLoadedGlobalConfig = true;
try {
systemStartCb();
//init system configinit vector databaseinit root user
await Promise.all([getInitConfig(), initVectorStore(), initRootUser()]);
getSystemPluginCb();
startMongoWatch();
// cron
startCron();
// start queue
startTrainingQueue(true);
} catch (error) {
addLog.error('init error', error);
exit(1);
}
});
return connectMongo();
}
async function initRootUser(retry = 3): Promise<any> {
export async function initRootUser(retry = 3): Promise<any> {
try {
const rootUser = await MongoUser.findOne({
username: 'root'

View File

@@ -7,97 +7,186 @@ import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
import { authTeamSpaceToken } from './team';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { authOutLinkValid } from '@fastgpt/service/support/permission/publish/authLink';
import {
AuthUserTypeEnum,
OwnerPermissionVal,
ReadPermissionVal
} from '@fastgpt/global/support/permission/constant';
import { AuthUserTypeEnum, ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { addLog } from '@fastgpt/service/common/system/log';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
/*
outLink: Must be the owner
token: team owner and chat owner have all permissions
检查chat的权限
1. 无 chatId仅校验 cookie、shareChat、teamChat 秘钥是否合法
2. 有 chatId校验用户是否有权限操作该 chat
* cookie + appId 校验
* shareId + outLinkUid 校验
* teamId + teamToken + appId 校验
Chat没有读写的权限之分鉴权过了都可以操作。
*/
const defaultResponseShow = {
responseDetail: true,
showNodeStatus: true,
showRawSource: true
};
export async function authChatCrud({
appId,
chatId,
shareId,
outLinkUid,
teamId: spaceTeamId,
teamToken,
per = OwnerPermissionVal,
...props
}: AuthModeType & {
appId: string;
chatId?: string;
shareId?: string;
outLinkUid?: string;
teamId?: string;
teamToken?: string;
}): Promise<{
teamId: string;
tmbId: string;
uid: string;
chat?: ChatSchema;
isOutLink: boolean;
uid?: string;
responseDetail: boolean;
showNodeStatus: boolean;
showRawSource: boolean;
authType?: `${AuthUserTypeEnum}`;
}> {
const isOutLink = Boolean((shareId || spaceTeamId) && outLinkUid);
if (!chatId) return { isOutLink, uid: outLinkUid, responseDetail: true };
if (!appId) return Promise.reject(ChatErrEnum.unAuthChat);
if (spaceTeamId && teamToken) {
const { uid, tmbId } = await authTeamSpaceToken({ teamId: spaceTeamId, teamToken });
if (!chatId)
return {
teamId: spaceTeamId,
tmbId,
uid,
...defaultResponseShow,
authType: AuthUserTypeEnum.teamDomain
};
const chat = await MongoChat.findOne({ appId, chatId, outLinkUid: uid }).lean();
if (!chat)
return {
teamId: spaceTeamId,
tmbId,
uid,
...defaultResponseShow,
authType: AuthUserTypeEnum.teamDomain
};
return {
teamId: spaceTeamId,
tmbId,
uid,
chat,
...defaultResponseShow,
authType: AuthUserTypeEnum.teamDomain
};
}
if (shareId && outLinkUid) {
const {
outLinkConfig,
uid,
appId: shareChatAppId
} = await authOutLink({ shareId, outLinkUid });
if (String(shareChatAppId) !== appId) return Promise.reject(ChatErrEnum.unAuthChat);
if (!chatId) {
return {
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showRawSource: outLinkConfig.showRawSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}
const chat = await MongoChat.findOne({ appId, chatId, outLinkUid: uid }).lean();
if (!chat) {
return {
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showRawSource: outLinkConfig.showRawSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}
return {
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
chat,
uid,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus ?? true,
showRawSource: outLinkConfig.showRawSource ?? false,
authType: AuthUserTypeEnum.outLink
};
}
// Cookie
const { teamId, tmbId, permission, authType } = await authApp({
req: props.req,
authToken: true,
authApiKey: true,
appId,
per: ReadPermissionVal
});
if (!chatId)
return {
teamId,
tmbId,
uid: tmbId,
...defaultResponseShow,
authType
};
const chat = await MongoChat.findOne({ appId, chatId }).lean();
if (!chat)
return {
teamId,
tmbId,
uid: tmbId,
...defaultResponseShow,
authType
};
const { uid, responseDetail } = await (async () => {
// outLink Auth
if (shareId && outLinkUid) {
const { uid, shareChat } = await authOutLink({ shareId, outLinkUid });
if (!chat || (chat.shareId === shareId && chat.outLinkUid === uid)) {
return { uid, responseDetail: shareChat.responseDetail };
}
return Promise.reject(ChatErrEnum.unAuthChat);
}
// auth team space chat
if (spaceTeamId && teamToken) {
const { uid } = await authTeamSpaceToken({ teamId: spaceTeamId, teamToken });
addLog.debug('Auth team token', { uid, spaceTeamId, teamToken, chatUid: chat?.outLinkUid });
if (!chat || (String(chat.teamId) === String(spaceTeamId) && chat.outLinkUid === uid)) {
return { uid, responseDetail: true };
}
return Promise.reject(ChatErrEnum.unAuthChat);
}
if (String(teamId) !== String(chat.teamId)) return Promise.reject(ChatErrEnum.unAuthChat);
if (permission.hasManagePer)
return {
teamId,
tmbId,
chat,
uid: tmbId,
...defaultResponseShow,
authType
};
if (String(tmbId) === String(chat.tmbId))
return {
teamId,
tmbId,
chat,
uid: tmbId,
...defaultResponseShow,
authType
};
if (!chat) return { id: outLinkUid, responseDetail: true };
// auth req
const { teamId, tmbId, permission } = await authApp({
req: props.req,
authToken: true,
authApiKey: true,
appId,
per: ReadPermissionVal
});
if (String(teamId) !== String(chat.teamId)) return Promise.reject(ChatErrEnum.unAuthChat);
if (permission.hasManagePer) return { uid: outLinkUid, responseDetail: true };
if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid, responseDetail: true };
return Promise.reject(ChatErrEnum.unAuthChat);
})();
if (!chat) return { isOutLink, uid, responseDetail };
return {
chat,
isOutLink,
uid,
responseDetail
};
return Promise.reject(ChatErrEnum.unAuthChat);
}
/*
Abandoned
Different chat source
1. token (header)
2. apikey (header)
@@ -116,15 +205,15 @@ export async function authChatCert(props: AuthModeType): Promise<{
const { teamId, teamToken, shareId, outLinkUid } = props.req.body as OutLinkChatAuthProps;
if (shareId && outLinkUid) {
const { shareChat } = await authOutLinkValid({ shareId });
const { outLinkConfig } = await authOutLinkValid({ shareId });
const { uid } = await authOutLinkInit({
outLinkUid,
tokenUrl: shareChat.limit?.hookUrl
tokenUrl: outLinkConfig.limit?.hookUrl
});
return {
teamId: String(shareChat.teamId),
tmbId: String(shareChat.tmbId),
teamId: String(outLinkConfig.teamId),
tmbId: String(outLinkConfig.tmbId),
authType: AuthUserTypeEnum.outLink,
apikey: '',
isOwner: false,

View File

@@ -27,7 +27,7 @@ export const authOutLink = async ({
}: ShareChatAuthProps): Promise<{
uid: string;
appId: string;
shareChat: OutLinkSchema;
outLinkConfig: OutLinkSchema;
}> => {
if (!outLinkUid) {
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
@@ -36,7 +36,7 @@ export const authOutLink = async ({
const { uid } = await authOutLinkInit({
outLinkUid,
tokenUrl: result.shareChat.limit?.hookUrl
tokenUrl: result.outLinkConfig.limit?.hookUrl
});
return {
@@ -54,21 +54,21 @@ export async function authOutLinkChatStart({
shareId: string;
}) {
// get outLink and app
const { shareChat, appId } = await authOutLinkValid({ shareId });
const { outLinkConfig, appId } = await authOutLinkValid({ shareId });
// check ai points and chat limit
const [{ user }, { uid }] = await Promise.all([
getUserChatInfoAndAuthTeamPoints(shareChat.tmbId),
authOutLinkChatLimit({ outLink: shareChat, ip, outLinkUid, question })
getUserChatInfoAndAuthTeamPoints(outLinkConfig.tmbId),
authOutLinkChatLimit({ outLink: outLinkConfig, ip, outLinkUid, question })
]);
return {
sourceName: shareChat.name,
teamId: shareChat.teamId,
tmbId: shareChat.tmbId,
sourceName: outLinkConfig.name,
teamId: outLinkConfig.teamId,
tmbId: outLinkConfig.tmbId,
authType: AuthUserTypeEnum.token,
responseDetail: shareChat.responseDetail,
showNodeStatus: shareChat.showNodeStatus,
responseDetail: outLinkConfig.responseDetail,
showNodeStatus: outLinkConfig.showNodeStatus,
user,
appId,
uid

View File

@@ -7,6 +7,7 @@ import {
AuthTeamTagTokenProps,
AuthTokenFromTeamDomainResponse
} from '@fastgpt/global/support/user/team/tag';
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
export async function getUserChatInfoAndAuthTeamPoints(tmbId: string) {
const tmb = (await MongoTeamMember.findById(tmbId, 'teamId userId').populate(
@@ -33,10 +34,13 @@ export async function authTeamSpaceToken({
teamToken: string;
}) {
// get outLink and app
const data = await authTeamTagToken({ teamId, teamToken });
const uid = data.uid;
const [{ uid }, member] = await Promise.all([
authTeamTagToken({ teamId, teamToken }),
MongoTeamMember.findOne({ teamId, role: TeamMemberRoleEnum.owner }, 'tmbId').lean()
]);
return {
uid
uid,
tmbId: member?._id!
};
}

View File

@@ -3,21 +3,25 @@ import { addLog } from '@fastgpt/service/common/system/log';
import { POST } from '@fastgpt/service/common/api/plusRequest';
import { FastGPTProUrl } from '@fastgpt/service/common/system/constants';
export function createUsage(data: CreateUsageProps) {
export async function createUsage(data: CreateUsageProps) {
if (!FastGPTProUrl) return;
if (data.totalPoints === 0) {
addLog.info('0 totalPoints', data);
}
try {
POST('/support/wallet/usage/createUsage', data);
} catch (error) {}
await POST('/support/wallet/usage/createUsage', data);
} catch (error) {
addLog.error('createUsage error', error);
}
}
export function concatUsage(data: ConcatUsageProps) {
export async function concatUsage(data: ConcatUsageProps) {
if (!FastGPTProUrl) return;
if (data.totalPoints === 0) {
addLog.info('0 totalPoints', data);
}
try {
POST('/support/wallet/usage/concatUsage', data);
} catch (error) {}
await POST('/support/wallet/usage/concatUsage', data);
} catch (error) {
addLog.error('concatUsage error', error);
}
}