4.8 test fix (#1397)

* adapt v1 chat init

* adapt v1 chat init

* adapt v1 chat init

* perf: message input line; fix: http request un stream

* perf: message input line; fix: http request un stream

* perf: message input line; fix: http request un stream

* perf: error tip
This commit is contained in:
Archer
2024-05-08 22:18:22 +08:00
committed by GitHub
parent 3c6e5a6e00
commit 917e4e9262
13 changed files with 167 additions and 146 deletions

View File

@@ -2,7 +2,7 @@ import { ErrType } from '../errorCode';
/* dataset: 502000 */ /* dataset: 502000 */
export enum AppErrEnum { export enum AppErrEnum {
unExist = 'unExist', unExist = 'appUnExist',
unAuthApp = 'unAuthApp' unAuthApp = 'unAuthApp'
} }
const appErrList = [ const appErrList = [

View File

@@ -2,8 +2,8 @@ import { ErrType } from '../errorCode';
/* dataset: 506000 */ /* dataset: 506000 */
export enum OpenApiErrEnum { export enum OpenApiErrEnum {
unExist = 'unExist', unExist = 'openapiUnExist',
unAuth = 'unAuth' unAuth = 'openapiUnAuth'
} }
const errList = [ const errList = [
{ {

View File

@@ -2,7 +2,7 @@ import { ErrType } from '../errorCode';
/* dataset: 505000 */ /* dataset: 505000 */
export enum OutLinkErrEnum { export enum OutLinkErrEnum {
unExist = 'unExist', unExist = 'outlinkUnExist',
unAuthLink = 'unAuthLink', unAuthLink = 'unAuthLink',
linkUnInvalid = 'linkUnInvalid', linkUnInvalid = 'linkUnInvalid',

View File

@@ -2,8 +2,8 @@ import { ErrType } from '../errorCode';
/* dataset: 507000 */ /* dataset: 507000 */
export enum PluginErrEnum { export enum PluginErrEnum {
unExist = 'unExist', unExist = 'pluginUnExist',
unAuth = 'unAuth' unAuth = 'pluginUnAuth'
} }
const errList = [ const errList = [
{ {

View File

@@ -15,7 +15,7 @@ export const VariableUpdateNode: FlowNodeTemplateType = {
targetHandle: getHandleConfig(true, true, true, true), targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/variable.png', avatar: '/imgs/workflow/variable.png',
name: '变量更新', name: '变量更新',
intro: '可以更新指定节点的输出值全局变量', intro: '可以更新指定节点的输出值或更新全局变量',
showStatus: true, showStatus: true,
isTool: false, isTool: false,
inputs: [ inputs: [

View File

@@ -290,7 +290,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
params, params,
mode: 'test' mode: props.mode === 'debug' ? 'test' : props.mode
}; };
// run module // run module

View File

@@ -45,6 +45,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
detail, detail,
appId, appId,
chatId, chatId,
stream,
responseChatItemId, responseChatItemId,
variables, variables,
node: { outputs }, node: { outputs },
@@ -132,7 +133,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
results[key] = valueTypeFormat(formatResponse[key], output.valueType); results[key] = valueTypeFormat(formatResponse[key], output.valueType);
} }
if (typeof formatResponse[NodeOutputKeyEnum.answerText] === 'string') { if (stream && typeof formatResponse[NodeOutputKeyEnum.answerText] === 'string') {
responseWrite({ responseWrite({
res, res,
event: detail ? SseResponseEventEnum.fastAnswer : undefined, event: detail ? SseResponseEventEnum.fastAnswer : undefined,

View File

@@ -85,7 +85,22 @@
"x": 1607.7142331269126, "x": 1607.7142331269126,
"y": -151.8669210746189 "y": -151.8669210746189
}, },
"inputs": [], "inputs": [
{
"key": "text",
"valueType": "string",
"label": "text",
"renderTypeList": ["reference"],
"description": "",
"canEdit": true,
"editField": {
"key": true,
"description": true,
"valueType": true
},
"value": ["CRT7oIEU8v2P", "pYKS0LB9gAr3"]
}
],
"outputs": [] "outputs": []
}, },
{ {
@@ -190,6 +205,13 @@
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any", "valueType": "any",
"type": "static" "type": "static"
},
{
"id": "pYKS0LB9gAr3",
"type": "dynamic",
"key": "text",
"valueType": "string",
"label": "text"
} }
] ]
} }

View File

@@ -357,9 +357,16 @@ const MessageInput = ({
// enter send.(pc or iframe && enter and unPress shift) // enter send.(pc or iframe && enter and unPress shift)
const isEnter = e.keyCode === 13; const isEnter = e.keyCode === 13;
if (isEnter && TextareaDom.current && (e.ctrlKey || e.altKey)) { if (isEnter && TextareaDom.current && (e.ctrlKey || e.altKey)) {
TextareaDom.current.value += '\n'; // Add a new line
const index = TextareaDom.current.selectionStart;
const val = TextareaDom.current.value;
TextareaDom.current.value = `${val.slice(0, index)}\n${val.slice(index)}`;
TextareaDom.current.selectionStart = index + 1;
TextareaDom.current.selectionEnd = index + 1;
TextareaDom.current.style.height = textareaMinH; TextareaDom.current.style.height = textareaMinH;
TextareaDom.current.style.height = `${TextareaDom.current.scrollHeight}px`; TextareaDom.current.style.height = `${TextareaDom.current.scrollHeight}px`;
return; return;
} }

View File

@@ -487,7 +487,6 @@ const WorkflowContextProvider = ({
// 3. Set entry node status to running // 3. Set entry node status to running
entryNodes.forEach((node) => { entryNodes.forEach((node) => {
if (runtimeNodeStatus[node.nodeId] !== 'wait') { if (runtimeNodeStatus[node.nodeId] !== 'wait') {
console.log(node.name);
onChangeNode({ onChangeNode({
nodeId: node.nodeId, nodeId: node.nodeId,
type: 'attr', type: 'attr',

View File

@@ -1,6 +1,5 @@
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response'; import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authApp } from '@fastgpt/service/support/permission/auth/app'; import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { getGuideModule, replaceAppChatConfig } from '@fastgpt/global/core/workflow/utils'; import { getGuideModule, replaceAppChatConfig } from '@fastgpt/global/core/workflow/utils';
import { getChatModelNameListByModules } from '@/service/core/app/workflow'; import { getChatModelNameListByModules } from '@/service/core/app/workflow';
@@ -10,78 +9,73 @@ import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat'; import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { NextAPI } from '@/service/middle/entry';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { async function handler(
try { req: NextApiRequest,
await connectToDatabase(); res: NextApiResponse
): Promise<InitChatResponse | void> {
let { appId, chatId, loadCustomFeedbacks } = req.query as InitChatProps;
let { appId, chatId, loadCustomFeedbacks } = req.query as InitChatProps; if (!appId) {
return jsonRes(res, {
if (!appId) { code: 501,
return jsonRes(res, { message: "You don't have an app yet"
code: 501,
message: "You don't have an app yet"
});
}
// auth app permission
const [{ app, tmbId }, chat] = await Promise.all([
authApp({
req,
authToken: true,
appId,
per: 'r'
}),
chatId ? MongoChat.findOne({ appId, chatId }) : undefined
]);
// auth chat permission
if (chat && !app.canWrite && String(tmbId) !== String(chat?.tmbId)) {
throw new Error(ChatErrEnum.unAuthChat);
}
// get app and history
const [{ history }, { nodes }] = await Promise.all([
getChatItems({
appId,
chatId,
limit: 30,
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback ${
DispatchNodeResponseKeyEnum.nodeResponse
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`
}),
getAppLatestVersion(app._id, app)
]);
jsonRes<InitChatResponse>(res, {
data: {
chatId,
appId,
title: chat?.title || '新对话',
userAvatar: undefined,
variables: chat?.variables || {},
history,
app: {
userGuideModule: replaceAppChatConfig({
node: getGuideModule(nodes),
variableList: chat?.variableList,
welcomeText: chat?.welcomeText
}),
chatModels: getChatModelNameListByModules(nodes),
name: app.name,
avatar: app.avatar,
intro: app.intro
}
}
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
}); });
} }
// auth app permission
const [{ app, tmbId }, chat] = await Promise.all([
authApp({
req,
authToken: true,
appId,
per: 'r'
}),
chatId ? MongoChat.findOne({ appId, chatId }) : undefined
]);
// auth chat permission
if (chat && !app.canWrite && String(tmbId) !== String(chat?.tmbId)) {
throw new Error(ChatErrEnum.unAuthChat);
}
// get app and history
const [{ history }, { nodes }] = await Promise.all([
getChatItems({
appId,
chatId,
limit: 30,
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback ${
DispatchNodeResponseKeyEnum.nodeResponse
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`
}),
getAppLatestVersion(app._id, app)
]);
return {
chatId,
appId,
title: chat?.title || '新对话',
userAvatar: undefined,
variables: chat?.variables || {},
history,
app: {
userGuideModule: replaceAppChatConfig({
node: getGuideModule(nodes),
variableList: chat?.variableList,
welcomeText: chat?.welcomeText
}),
chatModels: getChatModelNameListByModules(nodes),
name: app.name,
avatar: app.avatar,
intro: app.intro
}
};
} }
export default NextAPI(handler);
export const config = { export const config = {
api: { api: {
responseLimit: '10mb' responseLimit: '10mb'

View File

@@ -1,6 +1,4 @@
import type { NextApiRequest, NextApiResponse } from 'next'; import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { jsonRes } from '@fastgpt/service/common/response';
import { pushChatUsage } from '@/service/support/wallet/usage/push'; import { pushChatUsage } from '@/service/support/wallet/usage/push';
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants'; import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
import { authApp } from '@fastgpt/service/support/permission/auth/app'; import { authApp } from '@fastgpt/service/support/permission/auth/app';
@@ -9,8 +7,12 @@ import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team'; import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core/workflow/api'; import { PostWorkflowDebugProps, PostWorkflowDebugResponse } from '@/global/core/workflow/api';
import { authPluginCrud } from '@fastgpt/service/support/permission/auth/plugin'; import { authPluginCrud } from '@fastgpt/service/support/permission/auth/plugin';
import { NextAPI } from '@/service/middle/entry';
export default async function handler(req: NextApiRequest, res: NextApiResponse) { async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<PostWorkflowDebugResponse> {
const { const {
nodes = [], nodes = [],
edges = [], edges = [],
@@ -18,72 +20,65 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
appId, appId,
pluginId pluginId
} = req.body as PostWorkflowDebugProps; } = req.body as PostWorkflowDebugProps;
try {
await connectToDatabase();
if (!nodes) {
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');
}
/* user auth */ if (!nodes) {
const [{ teamId, tmbId }] = await Promise.all([ throw new Error('Prams Error');
authCert({
req,
authToken: true
}),
appId && authApp({ req, authToken: true, appId, per: 'r' }),
pluginId && authPluginCrud({ req, authToken: true, pluginId, per: 'r' })
]);
// auth balance
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
/* start process */
const { flowUsages, flowResponses, debugResponse } = await dispatchWorkFlow({
res,
mode: 'debug',
teamId,
tmbId,
user,
appId,
runtimeNodes: nodes,
runtimeEdges: edges,
variables,
query: [],
histories: [],
stream: false,
detail: true,
maxRunTimes: 200
});
pushChatUsage({
appName: '工作流Debug',
appId,
teamId,
tmbId,
source: UsageSourceEnum.fastgpt,
flowUsages
});
jsonRes<PostWorkflowDebugResponse>(res, {
data: {
...debugResponse,
flowResponses
}
});
} catch (err: any) {
jsonRes(res, {
code: 500,
error: err
});
} }
if (!Array.isArray(nodes)) {
throw new Error('Nodes is not array');
}
if (!Array.isArray(edges)) {
throw new Error('Edges is not array');
}
/* user auth */
const [{ teamId, tmbId }] = await Promise.all([
authCert({
req,
authToken: true
}),
appId && authApp({ req, authToken: true, appId, per: 'r' }),
pluginId && authPluginCrud({ req, authToken: true, pluginId, per: 'r' })
]);
// auth balance
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
/* start process */
const { flowUsages, flowResponses, debugResponse } = await dispatchWorkFlow({
res,
mode: 'debug',
teamId,
tmbId,
user,
appId,
runtimeNodes: nodes,
runtimeEdges: edges,
variables,
query: [],
histories: [],
stream: false,
detail: true,
maxRunTimes: 200
});
pushChatUsage({
appName: '工作流Debug',
appId,
teamId,
tmbId,
source: UsageSourceEnum.fastgpt,
flowUsages
});
return {
...debugResponse,
flowResponses
};
} }
export default NextAPI(handler);
export const config = { export const config = {
api: { api: {
bodyParser: { bodyParser: {

View File

@@ -34,11 +34,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
if (!chatId || !chatItemId) { if (!chatId || !chatItemId) {
return res.json({ return res.json({
[NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${customFeedback}"\\n\\n` [NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${customFeedback}"\\n\\n`,
text: customFeedback
}); });
} }
return res.json({}); res.json({
text: customFeedback
});
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.status(500).send(getErrText(err)); res.status(500).send(getErrText(err));