mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
Concat plugin to app (#1799)
This commit is contained in:
@@ -85,7 +85,14 @@ export const countGptMessagesTokens = (
|
||||
functionCall
|
||||
});
|
||||
} catch (error) {
|
||||
resolve(0);
|
||||
addLog.error('Count token error', error);
|
||||
const total = messages.reduce((sum, item) => {
|
||||
if (item.content) {
|
||||
return sum + item.content.length;
|
||||
}
|
||||
return sum;
|
||||
}, 0);
|
||||
resolve(total);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { MongoPlugin } from './schema';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { FlowNodeTypeEnum, defaultNodeVersion } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { pluginData2FlowNodeIO } from '@fastgpt/global/core/workflow/utils';
|
||||
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
import type { PluginRuntimeType, PluginTemplateType } from '@fastgpt/global/core/plugin/type.d';
|
||||
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { getHandleConfig } from '../../../global/core/workflow/template/utils';
|
||||
import { getHandleConfig } from '@fastgpt/global/core/workflow/template/utils';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { MongoApp } from '../schema';
|
||||
|
||||
/*
|
||||
plugin id rule:
|
||||
@@ -19,6 +19,7 @@ import { cloneDeep } from 'lodash';
|
||||
export async function splitCombinePluginId(id: string) {
|
||||
const splitRes = id.split('-');
|
||||
if (splitRes.length === 1) {
|
||||
// app id
|
||||
return {
|
||||
source: PluginSourceEnum.personal,
|
||||
pluginId: id
|
||||
@@ -33,6 +34,7 @@ export async function splitCombinePluginId(id: string) {
|
||||
|
||||
const getPluginTemplateById = async (id: string): Promise<PluginTemplateType> => {
|
||||
const { source, pluginId } = await splitCombinePluginId(id);
|
||||
|
||||
if (source === PluginSourceEnum.community) {
|
||||
const item = global.communityPlugins?.find((plugin) => plugin.id === pluginId);
|
||||
if (!item) return Promise.reject('plugin not found');
|
||||
@@ -40,8 +42,9 @@ const getPluginTemplateById = async (id: string): Promise<PluginTemplateType> =>
|
||||
return cloneDeep(item);
|
||||
}
|
||||
if (source === PluginSourceEnum.personal) {
|
||||
const item = await MongoPlugin.findById(id).lean();
|
||||
const item = await MongoApp.findById(id).lean();
|
||||
if (!item) return Promise.reject('plugin not found');
|
||||
|
||||
return {
|
||||
id: String(item._id),
|
||||
teamId: String(item.teamId),
|
||||
@@ -54,7 +57,7 @@ const getPluginTemplateById = async (id: string): Promise<PluginTemplateType> =>
|
||||
edges: item.edges,
|
||||
templateType: FlowNodeTemplateTypeEnum.personalPlugin,
|
||||
isTool: true,
|
||||
nodeVersion: item?.nodeVersion || ''
|
||||
version: item?.pluginData?.nodeVersion || defaultNodeVersion
|
||||
};
|
||||
}
|
||||
return Promise.reject('plugin not found');
|
||||
@@ -74,8 +77,7 @@ export async function getPluginPreviewNode({ id }: { id: string }): Promise<Flow
|
||||
intro: plugin.intro,
|
||||
showStatus: plugin.showStatus,
|
||||
isTool: plugin.isTool,
|
||||
nodeVersion: plugin.nodeVersion,
|
||||
version: '481',
|
||||
version: plugin.version,
|
||||
sourceHandle: getHandleConfig(true, true, true, true),
|
||||
targetHandle: getHandleConfig(true, true, true, true),
|
||||
...pluginData2FlowNodeIO(plugin.nodes)
|
@@ -1,8 +1,7 @@
|
||||
import { AppTypeEnum, AppTypeMap } from '@fastgpt/global/core/app/constants';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { connectionMongo, type Model } from '../../common/mongo';
|
||||
const { Schema, model, models } = connectionMongo;
|
||||
import type { AppSchema as AppType } from '@fastgpt/global/core/app/type.d';
|
||||
import { PermissionTypeEnum, PermissionTypeMap } from '@fastgpt/global/support/permission/constant';
|
||||
import {
|
||||
TeamCollectionName,
|
||||
TeamMemberCollectionName
|
||||
@@ -43,7 +42,7 @@ const AppSchema = new Schema({
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: AppTypeEnum.advanced,
|
||||
default: AppTypeEnum.workflow,
|
||||
enum: Object.values(AppTypeEnum)
|
||||
},
|
||||
version: {
|
||||
@@ -64,16 +63,11 @@ const AppSchema = new Schema({
|
||||
},
|
||||
|
||||
// role and auth
|
||||
permission: {
|
||||
type: String,
|
||||
enum: Object.keys(PermissionTypeMap),
|
||||
default: PermissionTypeEnum.private
|
||||
},
|
||||
teamTags: {
|
||||
type: [String]
|
||||
},
|
||||
|
||||
// tmp store
|
||||
// save app(Not publish)
|
||||
modules: {
|
||||
type: Array,
|
||||
default: []
|
||||
@@ -83,8 +77,16 @@ const AppSchema = new Schema({
|
||||
default: []
|
||||
},
|
||||
chatConfig: {
|
||||
type: chatConfigType,
|
||||
default: {}
|
||||
type: chatConfigType
|
||||
},
|
||||
// plugin config
|
||||
pluginData: {
|
||||
type: {
|
||||
nodeVersion: String,
|
||||
pluginUniId: String,
|
||||
apiSchemaStr: String, // http plugin
|
||||
customHeaders: String // http plugin
|
||||
}
|
||||
},
|
||||
|
||||
scheduledTriggerConfig: {
|
||||
|
@@ -24,8 +24,7 @@ const AppVersionSchema = new Schema({
|
||||
default: []
|
||||
},
|
||||
chatConfig: {
|
||||
type: chatConfigType,
|
||||
default: {}
|
||||
type: chatConfigType
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -68,10 +68,13 @@ const PluginSchema = new Schema({
|
||||
nodeVersion: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
inited: Boolean
|
||||
});
|
||||
|
||||
try {
|
||||
PluginSchema.index({ type: 1, init: 1 });
|
||||
PluginSchema.index({ teamId: 1, parentId: 1 });
|
||||
PluginSchema.index({ teamId: 1, name: 1, intro: 1 });
|
||||
} catch (error) {
|
||||
|
@@ -1,31 +0,0 @@
|
||||
import { connectionMongo, type Model } from '../../../common/mongo';
|
||||
const { Schema, model, models } = connectionMongo;
|
||||
import type { PluginItemSchema } from '@fastgpt/global/core/plugin/type.d';
|
||||
|
||||
import { PluginCollectionName } from '../schema';
|
||||
|
||||
export const ModuleCollectionName = 'plugins';
|
||||
|
||||
const PluginStoreSchema = new Schema({
|
||||
pluginId: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: PluginCollectionName,
|
||||
required: true
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
updateTime: {
|
||||
type: Date,
|
||||
default: () => new Date()
|
||||
},
|
||||
modules: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
});
|
||||
|
||||
export const MongoPluginStore: Model<PluginItemSchema> =
|
||||
models[ModuleCollectionName] || model(ModuleCollectionName, PluginStoreSchema);
|
||||
MongoPluginStore.syncIndexes();
|
@@ -3,8 +3,7 @@ import { dispatchWorkFlow } from '../index';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import { getPluginRuntimeById } from '../../../plugin/controller';
|
||||
import { authPluginCanUse } from '../../../../support/permission/auth/plugin';
|
||||
import { getPluginRuntimeById, splitCombinePluginId } from '../../../app/plugin/controller';
|
||||
import {
|
||||
getDefaultEntryNodeIds,
|
||||
initWorkflowEdgeStatus,
|
||||
@@ -13,6 +12,9 @@ import {
|
||||
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { updateToolInputValue } from '../agent/runTool/utils';
|
||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
import { authAppByTmbId } from '../../../../support/permission/app/auth';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
|
||||
type RunPluginProps = ModuleDispatchProps<{
|
||||
[key: string]: any;
|
||||
@@ -22,9 +24,9 @@ type RunPluginResponse = DispatchNodeResultType<{}>;
|
||||
export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPluginResponse> => {
|
||||
const {
|
||||
node: { pluginId },
|
||||
app: workflowApp,
|
||||
mode,
|
||||
teamId,
|
||||
tmbId,
|
||||
params: data
|
||||
} = props;
|
||||
|
||||
@@ -32,7 +34,16 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
return Promise.reject('pluginId can not find');
|
||||
}
|
||||
|
||||
await authPluginCanUse({ id: pluginId, teamId, tmbId });
|
||||
// auth plugin
|
||||
const { source } = await splitCombinePluginId(pluginId);
|
||||
if (source === PluginSourceEnum.personal) {
|
||||
await authAppByTmbId({
|
||||
appId: pluginId,
|
||||
teamId: workflowApp.teamId,
|
||||
tmbId: workflowApp.tmbId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
}
|
||||
const plugin = await getPluginRuntimeById(pluginId);
|
||||
|
||||
// concat dynamic inputs
|
||||
|
@@ -8,8 +8,7 @@ import {
|
||||
NodeInputKeyEnum
|
||||
} from '@fastgpt/global/core/workflow/constants';
|
||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import { splitCombinePluginId } from '../../../plugin/controller';
|
||||
import { authPluginCanUse } from '../../../../support/permission/auth/plugin';
|
||||
import { splitCombinePluginId } from '../../../app/plugin/controller';
|
||||
import { setEntryEntries, DYNAMIC_INPUT_KEY } from '../utils';
|
||||
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { PluginRuntimeType, PluginTemplateType } from '@fastgpt/global/core/plugin/type';
|
||||
@@ -73,8 +72,10 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
return Promise.reject('pluginId can not find');
|
||||
}
|
||||
|
||||
await authPluginCanUse({ id: pluginId, teamId, tmbId });
|
||||
const plugin = await getPluginRuntimeById(pluginId);
|
||||
if (plugin.teamId && plugin.teamId !== teamId) {
|
||||
return Promise.reject('plugin not found');
|
||||
}
|
||||
|
||||
// concat dynamic inputs
|
||||
const inputModule = plugin.modules.find((item) => item.flowType === FlowNodeTypeEnum.pluginInput);
|
||||
|
@@ -1,84 +0,0 @@
|
||||
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
|
||||
import { AuthModeType } from '../type';
|
||||
import { parseHeaderCert } from '../controller';
|
||||
import { getTmbInfoByTmbId } from '../../user/team/controller';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { MongoPlugin } from '../../../core/plugin/schema';
|
||||
import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin';
|
||||
import { PluginItemSchema } from '@fastgpt/global/core/plugin/type';
|
||||
import { splitCombinePluginId } from '../../../core/plugin/controller';
|
||||
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
|
||||
export async function authPluginCrud({
|
||||
pluginId,
|
||||
per = 'owner',
|
||||
...props
|
||||
}: AuthModeType & {
|
||||
pluginId: string;
|
||||
}): Promise<
|
||||
AuthResponseType & {
|
||||
plugin: PluginItemSchema;
|
||||
}
|
||||
> {
|
||||
const result = await parseHeaderCert(props);
|
||||
const { tmbId, teamId } = result;
|
||||
|
||||
const { role } = await getTmbInfoByTmbId({ tmbId });
|
||||
|
||||
const { plugin, isOwner, canWrite } = await (async () => {
|
||||
const plugin = await MongoPlugin.findOne({ _id: pluginId, teamId });
|
||||
|
||||
if (!plugin) {
|
||||
throw new Error(PluginErrEnum.unExist);
|
||||
}
|
||||
|
||||
const isOwner = String(plugin.tmbId) === tmbId || role === TeamMemberRoleEnum.owner;
|
||||
const canWrite = isOwner;
|
||||
|
||||
if (per === 'w' && !canWrite) {
|
||||
return Promise.reject(PluginErrEnum.unAuth);
|
||||
}
|
||||
if (per === 'owner' && !isOwner) {
|
||||
return Promise.reject(PluginErrEnum.unAuth);
|
||||
}
|
||||
|
||||
return {
|
||||
plugin,
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
...result,
|
||||
plugin,
|
||||
isOwner,
|
||||
canWrite
|
||||
};
|
||||
}
|
||||
|
||||
export async function authPluginCanUse({
|
||||
id,
|
||||
teamId,
|
||||
tmbId
|
||||
}: {
|
||||
id: string;
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
}) {
|
||||
const { source, pluginId } = await splitCombinePluginId(id);
|
||||
|
||||
if (source === PluginSourceEnum.community) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (source === PluginSourceEnum.personal) {
|
||||
const { role } = await getTmbInfoByTmbId({ tmbId });
|
||||
const plugin = await MongoPlugin.findOne({ _id: pluginId, teamId });
|
||||
if (!plugin) {
|
||||
return Promise.reject(PluginErrEnum.unExist);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
import { getTeamPlanStatus, getTeamStandPlan } from '../../support/wallet/sub/utils';
|
||||
import { MongoApp } from '../../core/app/schema';
|
||||
import { MongoPlugin } from '../../core/plugin/schema';
|
||||
import { MongoDataset } from '../../core/dataset/schema';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
@@ -64,26 +63,19 @@ export const checkTeamDatasetLimit = async (teamId: string) => {
|
||||
return Promise.reject(SystemErrEnum.communityVersionNumLimit);
|
||||
}
|
||||
};
|
||||
export const checkTeamAppLimit = async (teamId: string) => {
|
||||
export const checkTeamAppLimit = async (teamId: string, amount = 1) => {
|
||||
const [{ standardConstants }, appCount] = await Promise.all([
|
||||
getTeamStandPlan({ teamId }),
|
||||
MongoApp.count({ teamId, type: { $in: [AppTypeEnum.advanced, AppTypeEnum.simple] } })
|
||||
MongoApp.count({
|
||||
teamId,
|
||||
type: { $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin] }
|
||||
})
|
||||
]);
|
||||
|
||||
if (standardConstants && appCount >= standardConstants.maxAppAmount) {
|
||||
if (standardConstants && appCount + amount >= standardConstants.maxAppAmount) {
|
||||
return Promise.reject(TeamErrEnum.appAmountNotEnough);
|
||||
}
|
||||
};
|
||||
export const checkTeamPluginLimit = async (teamId: string) => {
|
||||
const [{ standardConstants }, pluginCount] = await Promise.all([
|
||||
getTeamStandPlan({ teamId }),
|
||||
MongoPlugin.count({ teamId })
|
||||
]);
|
||||
|
||||
if (standardConstants && pluginCount >= standardConstants.maxAppAmount) {
|
||||
return Promise.reject(TeamErrEnum.pluginAmountNotEnough);
|
||||
}
|
||||
};
|
||||
|
||||
export const checkTeamReRankPermission = async (teamId: string) => {
|
||||
const { standardConstants } = await getTeamStandPlan({
|
||||
|
@@ -1,21 +1,7 @@
|
||||
{
|
||||
"extends":"../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es2015",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts", "../**/*.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts", "../**/*.d.ts"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user