Plugin runtime (#2050)
* feat: plugin run (#1950) * feat: plugin run * fix * ui * fix * change user input type * fix * fix * temp * split out plugin chat * perf: chatbox * perf: chatbox * fix: plugin runtime (#2032) * fix: plugin runtime * fix * fix build * fix build * perf: chat send prompt * perf: chat log ux * perf: chatbox context and share page plugin runtime * perf: plugin run time config * fix: ts * feat: doc * perf: isPc check * perf: variable input render * feat: app search * fix: response box height * fix: phone ui * perf: lock * perf: plugin route * fix: chat (#2049) --------- Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import { AppFolderTypeList, AppTypeEnum } from '@fastgpt/global/core/app/constan
|
||||
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
export type ListAppBody = {
|
||||
parentId?: ParentIdType;
|
||||
@@ -55,8 +56,8 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
const searchMatch = searchKey
|
||||
? {
|
||||
$or: [
|
||||
{ name: { $regex: searchKey, $options: 'i' } },
|
||||
{ intro: { $regex: searchKey, $options: 'i' } }
|
||||
{ name: { $regex: new RegExp(`${replaceRegChars(searchKey)}`, 'i') } },
|
||||
{ intro: { $regex: new RegExp(`${replaceRegChars(searchKey)}`, 'i') } }
|
||||
]
|
||||
}
|
||||
: {};
|
||||
@@ -65,7 +66,14 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
return {
|
||||
// get all chat app
|
||||
teamId,
|
||||
type: { $in: [AppTypeEnum.workflow, AppTypeEnum.simple] },
|
||||
type: { $in: [AppTypeEnum.workflow, AppTypeEnum.simple, AppTypeEnum.plugin] },
|
||||
...searchMatch
|
||||
};
|
||||
}
|
||||
|
||||
if (searchKey) {
|
||||
return {
|
||||
teamId,
|
||||
...searchMatch
|
||||
};
|
||||
}
|
||||
@@ -74,8 +82,7 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
teamId,
|
||||
...(type && Array.isArray(type) && { type: { $in: type } }),
|
||||
...(type && { type }),
|
||||
...parseParentIdInMongo(parentId),
|
||||
...searchMatch
|
||||
...parseParentIdInMongo(parentId)
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { sseErrRes } from '@fastgpt/service/common/response';
|
||||
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
import { responseWrite } from '@fastgpt/service/common/response';
|
||||
import { pushChatUsage } from '@/service/support/wallet/usage/push';
|
||||
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
|
||||
import type {
|
||||
ChatItemType,
|
||||
ChatItemValueItemType,
|
||||
UserChatItemValueItemType
|
||||
} from '@fastgpt/global/core/chat/type';
|
||||
import type { UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
|
||||
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';
|
||||
@@ -18,10 +13,14 @@ import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
|
||||
import { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { updatePluginInputByVariables } from '@fastgpt/global/core/workflow/utils';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
|
||||
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
|
||||
|
||||
export type Props = {
|
||||
history: ChatItemType[];
|
||||
prompt: UserChatItemValueItemType[];
|
||||
messages: ChatCompletionMessageParam[];
|
||||
nodes: RuntimeNodeItemType[];
|
||||
edges: RuntimeEdgeItemType[];
|
||||
variables: Record<string, any>;
|
||||
@@ -29,7 +28,7 @@ export type Props = {
|
||||
appName: string;
|
||||
};
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
res.on('close', () => {
|
||||
res.end();
|
||||
});
|
||||
@@ -38,26 +37,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
res.end();
|
||||
});
|
||||
|
||||
let {
|
||||
nodes = [],
|
||||
edges = [],
|
||||
history = [],
|
||||
prompt,
|
||||
variables = {},
|
||||
appName,
|
||||
appId
|
||||
} = req.body as Props;
|
||||
let { nodes = [], edges = [], messages = [], variables = {}, appName, appId } = req.body as Props;
|
||||
try {
|
||||
await connectToDatabase();
|
||||
if (!history || !nodes || !prompt || prompt.length === 0) {
|
||||
throw new Error('Prams Error');
|
||||
}
|
||||
if (!Array.isArray(nodes)) {
|
||||
throw new Error('Nodes is not array');
|
||||
}
|
||||
if (!Array.isArray(edges)) {
|
||||
throw new Error('Edges is not array');
|
||||
}
|
||||
// [histories, user]
|
||||
const chatMessages = GPTMessages2Chats(messages);
|
||||
const userInput = chatMessages.pop()?.value as UserChatItemValueItemType[] | undefined;
|
||||
|
||||
/* user auth */
|
||||
const [{ app }, { teamId, tmbId }] = await Promise.all([
|
||||
@@ -67,6 +51,23 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
authToken: true
|
||||
})
|
||||
]);
|
||||
const isPlugin = app.type === AppTypeEnum.plugin;
|
||||
|
||||
if (!Array.isArray(nodes)) {
|
||||
throw new Error('Nodes is not array');
|
||||
}
|
||||
if (!Array.isArray(edges)) {
|
||||
throw new Error('Edges is not array');
|
||||
}
|
||||
|
||||
// Plugin need to replace inputs
|
||||
if (isPlugin) {
|
||||
nodes = updatePluginInputByVariables(nodes, variables);
|
||||
} else {
|
||||
if (!userInput) {
|
||||
throw new Error('Params Error');
|
||||
}
|
||||
}
|
||||
|
||||
// auth balance
|
||||
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
|
||||
@@ -82,8 +83,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
runtimeNodes: nodes,
|
||||
runtimeEdges: edges,
|
||||
variables,
|
||||
query: removeEmptyUserInput(prompt),
|
||||
histories: history,
|
||||
query: removeEmptyUserInput(userInput),
|
||||
histories: chatMessages,
|
||||
stream: true,
|
||||
detail: true,
|
||||
maxRunTimes: 200
|
||||
@@ -117,6 +118,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
}
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runti
|
||||
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
@@ -53,6 +54,8 @@ async function handler(
|
||||
}),
|
||||
getAppLatestVersion(app._id, app)
|
||||
]);
|
||||
const pluginInputs =
|
||||
app?.modules?.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)?.inputs ?? [];
|
||||
|
||||
return {
|
||||
chatId,
|
||||
@@ -72,7 +75,9 @@ async function handler(
|
||||
chatModels: getChatModelNameListByModules(nodes),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
intro: app.intro
|
||||
intro: app.intro,
|
||||
type: app.type,
|
||||
pluginInputs
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
|
||||
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
|
||||
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
@@ -47,7 +49,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
chatId,
|
||||
limit: 30,
|
||||
field: `dataId obj value userGoodFeedback userBadFeedback ${
|
||||
shareChat.responseDetail
|
||||
shareChat.responseDetail || app.type === AppTypeEnum.plugin
|
||||
? `adminFeedback ${DispatchNodeResponseKeyEnum.nodeResponse}`
|
||||
: ''
|
||||
} `
|
||||
@@ -56,11 +58,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
]);
|
||||
|
||||
// pick share response field
|
||||
histories.forEach((item) => {
|
||||
if (item.obj === ChatRoleEnum.AI) {
|
||||
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
|
||||
}
|
||||
});
|
||||
app.type !== AppTypeEnum.plugin &&
|
||||
histories.forEach((item) => {
|
||||
if (item.obj === ChatRoleEnum.AI) {
|
||||
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
|
||||
}
|
||||
});
|
||||
|
||||
jsonRes<InitChatResponse>(res, {
|
||||
data: {
|
||||
@@ -82,7 +85,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
chatModels: getChatModelNameListByModules(nodes),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
intro: app.intro
|
||||
intro: app.intro,
|
||||
type: app.type,
|
||||
pluginInputs:
|
||||
app?.modules?.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)
|
||||
?.inputs ?? []
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@ import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
|
||||
import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils';
|
||||
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
@@ -58,11 +60,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
]);
|
||||
|
||||
// pick share response field
|
||||
histories.forEach((item) => {
|
||||
if (item.obj === ChatRoleEnum.AI) {
|
||||
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
|
||||
}
|
||||
});
|
||||
app.type !== AppTypeEnum.plugin &&
|
||||
histories.forEach((item) => {
|
||||
if (item.obj === ChatRoleEnum.AI) {
|
||||
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
|
||||
}
|
||||
});
|
||||
|
||||
jsonRes<InitChatResponse>(res, {
|
||||
data: {
|
||||
@@ -83,7 +86,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
chatModels: getChatModelNameListByModules(nodes),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
intro: app.intro
|
||||
intro: app.intro,
|
||||
type: app.type,
|
||||
pluginInputs:
|
||||
app?.modules?.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)
|
||||
?.inputs ?? []
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user