V4.8.17 feature (#3485)

* feat: add third party account config (#3443)

* temp

* editor workflow variable style

* add team to dispatch

* i18n

* delete console

* change openai account position

* fix

* fix

* fix

* fix

* fix

* 4.8.17 test (#3461)

* perf: external provider config

* perf: ui

* feat: add template config (#3434)

* change template position

* template config

* delete console

* delete

* fix

* fix

* perf: Mongo visutal field (#3464)

* remve invalid code

* perf: team member visutal code

* perf: virtual search; perf: search test data

* fix: ts

* fix: image response headers

* perf: template code

* perf: auth layout;perf: auto save (#3472)

* perf: auth layout

* perf: auto save

* perf: auto save

* fix: template guide display & http input support external variables (#3475)

* fix: template guide display

* http editor support external workflow variables

* perf: auto save;fix: ifelse checker line break; (#3478)

* perf: auto save

* perf: auto save

* fix: ifelse checker line break

* perf: doc

* perf: doc

* fix: update var type error

* 4.8.17 test (#3479)

* perf: auto save

* perf: auto save

* perf: template code

* 4.8.17 test (#3480)

* perf: auto save

* perf: auto save

* perf: model price model

* feat: add react memo

* perf: model provider filter

* fix: ts (#3481)

* perf: auto save

* perf: auto save

* fix: ts

* simple app tool select (#3473)

* workflow plugin userguide & simple tool ui

* simple tool filter

* reuse component

* change component to hook

* fix

* perf: too selector modal (#3484)

* perf: auto save

* perf: auto save

* perf: markdown render

* perf: too selector

* fix: app version require tmbId

* perf: templates refresh

* perf: templates refresh

* hide auto save error tip

* perf: toolkit guide

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2024-12-27 20:05:12 +08:00
committed by GitHub
parent a209856d48
commit b520988c64
207 changed files with 2943 additions and 1378 deletions

View File

@@ -0,0 +1,39 @@
import { NextAPI } from '@/service/middleware/entry';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { NextApiRequest, NextApiResponse } from 'next';
async function handler(req: NextApiRequest, res: NextApiResponse) {
await authCert({ req, authRoot: true });
const users = await MongoUser.find(
{ openaiAccount: { $exists: true, $ne: null } },
'_id openaiAccount'
);
console.log(`${users.length} 个用户需要更新`);
let count = 0;
for (const user of users) {
await mongoSessionRun(async (session) => {
await MongoTeam.updateOne(
{ ownerId: user._id },
{
$set: { openaiAccount: (user as any).openaiAccount }
},
{ session }
);
// @ts-ignore
user.openaiAccount = undefined;
await user.save({ session });
});
count++;
console.log(`已更新 ${count} 个用户`);
}
return { success: true };
}
export default NextAPI(handler);

View File

@@ -94,6 +94,7 @@ async function initHttp(teamId?: string): Promise<any> {
await MongoAppVersion.create(
[
{
tmbId: plugin.tmbId,
appId: newPluginId,
nodes: item.modules,
edges: item.edges
@@ -166,6 +167,7 @@ async function initPlugin(teamId?: string): Promise<any> {
await MongoAppVersion.create(
[
{
tmbId: plugin.tmbId,
appId: newPluginId,
nodes: plugin.modules,
edges: plugin.edges

View File

@@ -40,6 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
res.setHeader('Content-Type', `${file.contentType}; charset=${encoding}`);
res.setHeader('Cache-Control', 'public, max-age=31536000');
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(file.filename)}"`);
res.setHeader('Content-Length', file.length);
stream.pipe(res);

View File

@@ -40,6 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
res.setHeader('Content-Type', `${file.contentType}; charset=${encoding}`);
res.setHeader('Cache-Control', 'public, max-age=31536000');
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(filename)}"`);
res.setHeader('Content-Length', file.length);
stream.pipe(res);

View File

@@ -45,8 +45,9 @@ async function handler(req: ApiRequestProps<CreateAppBody>) {
// 上限校验
await checkTeamAppLimit(teamId);
const tmb = await MongoTeamMember.findById({ _id: tmbId });
const user = await MongoUser.findById({ _id: tmb?.userId });
const tmb = await MongoTeamMember.findById({ _id: tmbId }, 'userId').populate<{
user: { avatar: string; username: string };
}>('user', 'avatar username');
// 创建app
const appId = await onCreateApp({
@@ -59,8 +60,8 @@ async function handler(req: ApiRequestProps<CreateAppBody>) {
chatConfig,
teamId,
tmbId,
userAvatar: user?.avatar,
username: user?.username
userAvatar: tmb?.user?.avatar,
username: tmb?.user?.username
});
pushTrack.createApp({
@@ -132,6 +133,7 @@ export const onCreateApp = async ({
await MongoAppVersion.create(
[
{
tmbId,
appId,
nodes: modules,
edges,

View File

@@ -45,7 +45,8 @@ async function handler(
currentCost: plugin.currentCost,
hasTokenFee: plugin.hasTokenFee,
author: plugin.author,
instructions: plugin.userGuide
instructions: plugin.userGuide,
courseUrl: plugin.courseUrl
}))
.filter((item) => {
if (searchKey) {

View File

@@ -1,8 +1,8 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { NextAPI } from '@/service/middleware/entry';
import { TemplateMarketItemType } from '@fastgpt/global/core/workflow/type';
import { getTemplateMarketItemDetail } from '@/service/core/app/template';
import { AppTemplateSchemaType } from '@fastgpt/global/core/app/type';
import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register';
type Props = {
templateId: string;
@@ -11,11 +11,13 @@ type Props = {
async function handler(
req: NextApiRequest,
res: NextApiResponse<any>
): Promise<TemplateMarketItemType | undefined> {
): Promise<AppTemplateSchemaType | undefined> {
await authCert({ req, authToken: true });
const { templateId } = req.query as Props;
return getTemplateMarketItemDetail(templateId);
const templateMarketItems: AppTemplateSchemaType[] = await getAppTemplatesAndLoadThem();
return templateMarketItems.find((item) => item.templateId === templateId);
}
export default NextAPI(handler);

View File

@@ -1,16 +1,53 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import type { NextApiResponse } from 'next';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { NextAPI } from '@/service/middleware/entry';
import { TemplateMarketListItemType } from '@fastgpt/global/core/workflow/type';
import { getTemplateMarketItemList } from '@/service/core/app/template';
import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register';
import { AppTemplateSchemaType } from '@fastgpt/global/core/app/type';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { ApiRequestProps } from '@fastgpt/service/type/next';
export type ListParams = {
isQuickTemplate?: boolean;
type?: AppTypeEnum | 'all';
};
async function handler(
req: NextApiRequest,
req: ApiRequestProps<ListParams>,
res: NextApiResponse<any>
): Promise<TemplateMarketListItemType[]> {
): Promise<AppTemplateSchemaType[]> {
await authCert({ req, authToken: true });
return getTemplateMarketItemList();
const { isQuickTemplate = false, type = 'all' } = req.query;
const templateMarketItems = await getAppTemplatesAndLoadThem();
let filteredItems = templateMarketItems.filter((item) => {
if (!item.isActive) return false;
if (type === 'all') return true;
return item.type === type;
});
if (isQuickTemplate) {
if (filteredItems.some((item) => item.isQuickTemplate !== undefined)) {
filteredItems = filteredItems.filter((item) => item.isQuickTemplate);
} else {
filteredItems = filteredItems.slice(0, 3);
}
}
return filteredItems.map((item) => {
return {
templateId: item.templateId,
name: item.name,
intro: item.intro,
avatar: item.avatar,
tags: item.tags,
type: item.type,
author: item.author,
userGuide: item.userGuide,
workflow: {}
};
});
}
export default NextAPI(handler);

View File

@@ -11,12 +11,9 @@ import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
async function handler(
req: ApiRequestProps<PostPublishAppProps>,
res: NextApiResponse<any>
): Promise<{}> {
async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
const { nodes = [], edges = [], chatConfig, isPublish, versionName } = req.body;
const { nodes = [], edges = [], chatConfig, isPublish, versionName, autoSave } = req.body;
const { app, tmbId } = await authApp({ appId, req, per: WritePermissionVal, authToken: true });
@@ -25,6 +22,15 @@ async function handler(
isPlugin: app.type === AppTypeEnum.plugin
});
if (autoSave) {
return MongoApp.findByIdAndUpdate(appId, {
modules: formatNodes,
edges,
chatConfig,
updateTime: new Date()
});
}
await mongoSessionRun(async (session) => {
// create version histories
const [{ _id }] = await MongoAppVersion.create(
@@ -70,8 +76,6 @@ async function handler(
}
);
});
return {};
}
export default NextAPI(handler);

View File

@@ -10,7 +10,7 @@ import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { getUserChatInfoAndAuthTeamPoints } from '@fastgpt/service/support/permission/auth/team';
import { StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
import {
concatHistories,
@@ -115,7 +115,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
})();
const limit = getMaxHistoryLimitFromNodes(nodes);
const [{ histories }, chatDetail, { user }] = await Promise.all([
const [{ histories }, chatDetail, { timezone, externalProvider }] = await Promise.all([
getChatItems({
appId,
chatId,
@@ -158,7 +158,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
res,
requestOrigin: req.headers.origin,
mode: 'test',
user,
timezone,
externalProvider,
uid: tmbId,
runningAppInfo: {
@@ -204,7 +205,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const { text: userInteractiveVal } = chatValue2RuntimePrompt(userQuestion.value);
const newTitle = isPlugin
? variables.cTime ?? getSystemTime(user.timezone)
? variables.cTime ?? getSystemTime(timezone)
: getChatTitleFromChatMessage(userQuestion);
const aiResponse: AIChatItemType & { dataId?: string } = {

View File

@@ -11,6 +11,7 @@ import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controller';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { NextAPI } from '@/service/middleware/entry';
import { UserModelSchema } from '@fastgpt/global/support/user/type';
async function handler(req: NextApiRequest, res: NextApiResponse) {
let { chatId, shareId, outLinkUid } = req.query as InitOutLinkChatProps;
@@ -20,7 +21,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// auth app permission
const [tmb, chat, app] = await Promise.all([
MongoTeamMember.findById(outLinkConfig.tmbId, '_id userId').populate('userId', 'avatar').lean(),
MongoTeamMember.findById(outLinkConfig.tmbId, '_id userId')
.populate<{ user: UserModelSchema }>('user', 'avatar')
.lean(),
MongoChat.findOne({ appId, chatId, shareId }).lean(),
MongoApp.findById(appId).lean()
]);
@@ -45,8 +48,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
chatId,
appId: app._id,
title: chat?.title,
//@ts-ignore
userAvatar: tmb?.userId?.avatar,
userAvatar: tmb?.user?.avatar,
variables: chat?.variables,
app: {
chatConfig: getAppChatConfig({

View File

@@ -66,9 +66,9 @@ async function handler(
return {
type: DatasetSourceReadTypeEnum.apiFile,
sourceId: collection.apiFileId,
apiServer: collection.datasetId.apiServer,
feishuServer: collection.datasetId.feishuServer,
yuqueServer: collection.datasetId.yuqueServer
apiServer: collection.dataset.apiServer,
feishuServer: collection.dataset.feishuServer,
yuqueServer: collection.dataset.yuqueServer
};
}
if (collection.type === DatasetCollectionTypeEnum.externalFile) {
@@ -90,12 +90,12 @@ async function handler(
return mongoSessionRun(async (session) => {
const { collectionId } = await createCollectionAndInsertData({
dataset: collection.datasetId,
dataset: collection.dataset,
rawText,
createCollectionParams: {
teamId: collection.teamId,
tmbId: collection.tmbId,
datasetId: collection.datasetId._id,
datasetId: collection.dataset._id,
name: collection.name,
type: collection.type,

View File

@@ -25,7 +25,7 @@ async function handler(req: NextApiRequest) {
// find all delete id
const collections = await findCollectionAndChild({
teamId,
datasetId: collection.datasetId._id,
datasetId: collection.datasetId,
collectionId,
fields: '_id teamId datasetId fileId metadata'
});

View File

@@ -37,7 +37,7 @@ async function handler(req: NextApiRequest): Promise<DatasetCollectionItemType>
...collection,
...getCollectionSourceData(collection),
tags: await collectionTagsToTagLabel({
datasetId: collection.datasetId._id,
datasetId: collection.datasetId,
tags: collection.tags
}),
permission,

View File

@@ -148,9 +148,9 @@ async function handler(
return collection.rawLink;
}
if (collection.type === DatasetCollectionTypeEnum.apiFile && collection.apiFileId) {
const apiServer = collection.datasetId.apiServer;
const feishuServer = collection.datasetId.feishuServer;
const yuqueServer = collection.datasetId.yuqueServer;
const apiServer = collection.dataset.apiServer;
const feishuServer = collection.dataset.feishuServer;
const yuqueServer = collection.dataset.yuqueServer;
if (apiServer) {
return useApiDatasetRequest({ apiServer }).getFilePreviewUrl({
@@ -170,11 +170,8 @@ async function handler(
return '';
}
if (collection.type === DatasetCollectionTypeEnum.externalFile) {
if (collection.externalFileId && collection.datasetId.externalReadUrl) {
return collection.datasetId.externalReadUrl.replace(
'{{fileId}}',
collection.externalFileId
);
if (collection.externalFileId && collection.dataset.externalReadUrl) {
return collection.dataset.externalReadUrl.replace('{{fileId}}', collection.externalFileId);
}
if (collection.externalFileUrl) {
return collection.externalFileUrl;

View File

@@ -100,7 +100,7 @@ async function handler(req: ApiRequestProps<UpdateDatasetCollectionParams>) {
const collectionTags = await createOrGetCollectionTags({
tags,
teamId,
datasetId: collection.datasetId._id,
datasetId: collection.datasetId,
session
});

View File

@@ -45,7 +45,7 @@ async function handler(req: NextApiRequest) {
// auth collection and get dataset
const [
{
datasetId: { _id: datasetId, vectorModel }
dataset: { _id: datasetId, vectorModel }
}
] = await Promise.all([getCollectionWithDataset(collectionId)]);

View File

@@ -31,7 +31,7 @@ async function handler(
const queryReg = new RegExp(`${replaceRegChars(searchText)}`, 'i');
const match = {
teamId,
datasetId: collection.datasetId._id,
datasetId: collection.datasetId,
collectionId,
...(searchText.trim()
? {

View File

@@ -1,9 +1,6 @@
/* push data to training queue */
import type { NextApiRequest, NextApiResponse } from 'next';
import type {
PushDatasetDataProps,
PushDatasetDataResponse
} from '@fastgpt/global/core/dataset/api.d';
import type { PushDatasetDataProps } from '@fastgpt/global/core/dataset/api.d';
import { authDatasetCollection } from '@fastgpt/service/support/permission/dataset/auth';
import { checkDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
import { predictDataLimitLength } from '@fastgpt/global/core/dataset/utils';
@@ -42,9 +39,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
...body,
teamId,
tmbId,
datasetId: collection.datasetId._id,
agentModel: collection.datasetId.agentModel,
vectorModel: collection.datasetId.vectorModel
datasetId: collection.datasetId,
agentModel: collection.dataset.agentModel,
vectorModel: collection.dataset.vectorModel
});
}

View File

@@ -12,7 +12,7 @@ async function handler(req: ApiRequestProps<UpdateDatasetDataProps>) {
// auth data permission
const {
collection: {
datasetId: { vectorModel }
dataset: { vectorModel }
},
teamId,
tmbId

View File

@@ -32,7 +32,7 @@ async function handler(
const queryReg = new RegExp(`${replaceRegChars(searchText)}`, 'i');
const match = {
teamId,
datasetId: collection.datasetId._id,
datasetId: collection.datasetId,
collectionId,
...(searchText.trim()
? {

View File

@@ -4,7 +4,7 @@ import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { dispatchWorkFlow } from '@fastgpt/service/core/workflow/dispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { getUserChatInfoAndAuthTeamPoints } from '@fastgpt/service/support/permission/auth/team';
import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core/workflow/api';
import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
@@ -37,7 +37,7 @@ async function handler(
]);
// auth balance
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
const { timezone, externalProvider } = await getUserChatInfoAndAuthTeamPoints(tmbId);
/* start process */
const { flowUsages, flowResponses, debugResponse, newVariables } = await dispatchWorkFlow({
@@ -50,7 +50,8 @@ async function handler(
tmbId
},
uid: tmbId,
user,
timezone,
externalProvider,
runtimeNodes: nodes,
runtimeEdges: edges,
variables,

View File

@@ -2,14 +2,39 @@ import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserDetail } from '@fastgpt/service/support/user/controller';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { UserType } from '@fastgpt/global/support/user/type';
export type TokenLoginQuery = {};
export type TokenLoginBody = {};
export type TokenLoginResponse = {};
export type TokenLoginResponse = UserType;
async function handler(
req: ApiRequestProps<TokenLoginBody, TokenLoginQuery>,
_res: ApiResponseType<any>
): Promise<TokenLoginResponse> {
const { tmbId } = await authCert({ req, authToken: true });
return getUserDetail({ tmbId });
const user = await getUserDetail({ tmbId });
// Remove sensitive information
if (user.team.lafAccount) {
user.team.lafAccount = {
appid: user.team.lafAccount.appid,
token: '',
pat: ''
};
}
if (user.team.openaiAccount) {
user.team.openaiAccount = {
key: '',
baseUrl: user.team.openaiAccount.baseUrl
};
}
if (user.team.externalWorkflowVariables) {
user.team.externalWorkflowVariables = Object.fromEntries(
Object.entries(user.team.externalWorkflowVariables).map(([key, value]) => [key, ''])
);
}
return user;
}
export default NextAPI(handler);

View File

@@ -1,7 +1,6 @@
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { UserUpdateParams } from '@/types/user';
import { getAIApi, openaiBaseUrl } from '@fastgpt/service/core/ai/config';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
/* update user info */
@@ -14,7 +13,7 @@ async function handler(
req: ApiRequestProps<UserAccountUpdateBody, UserAccountUpdateQuery>,
_res: ApiResponseType<any>
): Promise<UserAccountUpdateResponse> {
const { avatar, timezone, openaiAccount, lafAccount } = req.body;
const { avatar, timezone } = req.body;
const { tmbId } = await authCert({ req, authToken: true });
const tmb = await MongoTeamMember.findById(tmbId);
@@ -22,25 +21,6 @@ async function handler(
throw new Error('can not find it');
}
const userId = tmb.userId;
// auth key
if (openaiAccount?.key) {
console.log('auth user openai key', openaiAccount?.key);
const baseUrl = openaiAccount?.baseUrl || openaiBaseUrl;
openaiAccount.baseUrl = baseUrl;
const ai = getAIApi({
userKey: openaiAccount
});
const response = await ai.chat.completions.create({
model: 'gpt-4o-mini',
max_tokens: 1,
messages: [{ role: 'user', content: 'hi' }]
});
if (response?.choices?.[0]?.message?.content === undefined) {
throw new Error('Key response is empty');
}
}
// 更新对应的记录
await MongoUser.updateOne(
@@ -49,9 +29,7 @@ async function handler(
},
{
...(avatar && { avatar }),
...(timezone && { timezone }),
openaiAccount: openaiAccount?.key ? openaiAccount : null,
lafAccount: lafAccount?.token ? lafAccount : null
...(timezone && { timezone })
}
);

View File

@@ -0,0 +1,50 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import axios from 'axios';
import { addLog } from '@fastgpt/service/common/system/log';
export type checkUsageQuery = { key: string };
export type checkUsageBody = {};
export type checkUsageResponse =
| {
total: number;
used: number;
}
| undefined;
async function handler(
req: ApiRequestProps<checkUsageBody, checkUsageQuery>,
res: ApiResponseType<any>
): Promise<checkUsageResponse> {
try {
const { key } = req.query;
const { tmb } = await authUserPer({ req, authToken: true, per: ReadPermissionVal });
const url = global.feConfigs.externalProviderWorkflowVariables?.find(
(item) => item.key === key
)?.url;
if (!url || !tmb.externalWorkflowVariables?.[key]) return undefined;
const { data } = await axios.get<checkUsageResponse>(url, {
headers: {
Authorization: `Bearer ${tmb.externalWorkflowVariables[key]}`
}
});
if (!data) return undefined;
return {
total: data.total || 0,
used: data.used || 0
};
} catch (error) {
addLog.debug('checkUsage error', { error });
}
}
export default NextAPI(handler);

View File

@@ -33,7 +33,7 @@ import {
removeEmptyUserInput
} from '@fastgpt/global/core/chat/utils';
import { updateApiKeyUsage } from '@fastgpt/service/support/openapi/tools';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { getUserChatInfoAndAuthTeamPoints } from '@fastgpt/service/support/permission/auth/team';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { UserModelSchema } from '@fastgpt/global/support/user/type';
@@ -59,6 +59,7 @@ import { rewriteNodeOutputByHistories } from '@fastgpt/global/core/workflow/runt
import { getWorkflowResponseWrite } from '@fastgpt/service/core/workflow/dispatch/utils';
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
import { getPluginInputsFromStoreNodes } from '@fastgpt/global/core/app/plugin/utils';
import { ExternalProviderType } from '@fastgpt/global/core/workflow/runtime/type';
type FastGptWebChatProps = {
chatId?: string; // undefined: get histories from messages, '': new chat, 'xxxxx': get histories from db
@@ -80,7 +81,8 @@ export type Props = ChatCompletionCreateParams &
type AuthResponseType = {
teamId: string;
tmbId: string;
user: UserModelSchema;
timezone: string;
externalProvider: ExternalProviderType;
app: AppSchema;
responseDetail?: boolean;
showNodeStatus?: boolean;
@@ -154,7 +156,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const {
teamId,
tmbId,
user,
timezone,
externalProvider,
app,
responseDetail,
authType,
@@ -269,7 +272,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
res,
requestOrigin: req.headers.origin,
mode: 'chat',
user,
timezone,
externalProvider,
runningAppInfo: {
id: String(app._id),
@@ -314,7 +318,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const { text: userInteractiveVal } = chatValue2RuntimePrompt(userQuestion.value);
const newTitle = isPlugin
? variables.cTime ?? getSystemTime(user.timezone)
? variables.cTime ?? getSystemTime(timezone)
: getChatTitleFromChatMessage(userQuestion);
const aiResponse: AIChatItemType & { dataId?: string } = {
@@ -459,8 +463,18 @@ const authShareChat = async ({
shareId: string;
chatId?: string;
}): Promise<AuthResponseType> => {
const { teamId, tmbId, user, appId, authType, responseDetail, showNodeStatus, uid, sourceName } =
await authOutLinkChatStart(data);
const {
teamId,
tmbId,
timezone,
externalProvider,
appId,
authType,
responseDetail,
showNodeStatus,
uid,
sourceName
} = await authOutLinkChatStart(data);
const app = await MongoApp.findById(appId).lean();
if (!app) {
@@ -477,8 +491,9 @@ const authShareChat = async ({
sourceName,
teamId,
tmbId,
user,
app,
timezone,
externalProvider,
apikey: '',
authType,
responseAllData: false,
@@ -508,7 +523,7 @@ const authTeamSpaceChat = async ({
return Promise.reject('app is empty');
}
const [chat, { user }] = await Promise.all([
const [chat, { timezone, externalProvider }] = await Promise.all([
MongoChat.findOne({ appId, chatId }).lean(),
getUserChatInfoAndAuthTeamPoints(app.tmbId)
]);
@@ -520,8 +535,9 @@ const authTeamSpaceChat = async ({
return {
teamId,
tmbId: app.tmbId,
user,
app,
timezone,
externalProvider,
authType: AuthUserTypeEnum.outLink,
apikey: '',
responseAllData: false,
@@ -588,7 +604,7 @@ const authHeaderRequest = async ({
}
})();
const [{ user }, chat] = await Promise.all([
const [{ timezone, externalProvider }, chat] = await Promise.all([
getUserChatInfoAndAuthTeamPoints(tmbId),
MongoChat.findOne({ appId, chatId }).lean()
]);
@@ -605,7 +621,8 @@ const authHeaderRequest = async ({
return {
teamId,
tmbId,
user,
timezone,
externalProvider,
app,
apikey,
authType,