V4.9.5 feature (#4520)
* readme * Add queue log * Test interactive (#4509) * Support nested node interaction (#4503) * feat: Add a new InteractiveContext type and update InteractiveBasicType, adding an optional context property to support more complex interaction state management. * feat: Enhance workflow interactivity by adding InteractiveContext support and updating dispatch logic to manage nested contexts and entry nodes more effectively. * feat: Refactor dispatchWorkFlow to utilize InteractiveContext for improved context management * feat: Enhance entry node resolution by adding validation for entryNodeIds and recursive search in InteractiveContext * feat: Remove workflowDepth from InteractiveContext and update recovery logic to utilize parentContext for improved context management * feat: Update getWorkflowEntryNodeIds to use lastInteractive for improved context handling in runtime nodes * feat: Add lastInteractive support to enhance context management across workflow components * feat: Enhance interactive workflow by adding stopForInteractive flag and improving memory edge validation in runtime logic * feat: Refactor InteractiveContext by removing interactiveAppId and updating runtime edge handling in dispatchRunApp for improved context management * feat: Simplify runtime node and edge initialization in dispatchRunApp by using ternary operators for improved readability and maintainability * feat: Improve memory edge validation in initWorkflowEdgeStatus by adding detailed comments for better understanding of subset checks and recursive context searching * feat: Remove commented-out current level information from InteractiveContext for cleaner code and improved readability * feat: Simplify stopForInteractive check in dispatchWorkFlow for improved code clarity and maintainability * feat: Remove stopForInteractive handling and related references for improved code clarity and maintainability * feat: Add interactive response handling in dispatchRunAppNode for enhanced workflow interactivity * feat: Add context property to InteractiveBasicType and InteractiveNodeType for improved interactivity management * feat: remove comments * feat: Remove the node property from ChatDispatchProps to simplify type definitions * feat: Remove workflowInteractiveResponse from dispatchRunAppNode for cleaner code * feat: Refactor interactive value handling in chat history processing for improved clarity * feat: Simplify initWorkflowEdgeStatus logic for better readability and maintainability * feat: Add workflowInteractiveResponse to dispatchWorkFlow for enhanced functionality * feat: Enhance interactive response handling with nested children support * feat: Remove commented-out code for interactive node handling to improve clarity * feat: remove InteractiveContext type * feat: Refactor UserSelectInteractive and UserInputInteractive params for improved structure and clarity * feat: remove * feat: The front end supports extracting the deepest interaction parameters to enhance interaction processing * feat: The front end supports extracting the deepest interaction parameters to enhance interaction processing * fix: handle undefined interactive values in runtimeEdges and runtimeNodes initialization * fix: handle undefined interactive values in runtimeNodes and runtimeEdges initialization * fix: update runtimeNodes and runtimeEdges initialization to use last interactive value * fix: remove unused imports and replace getLastInteractiveValue with lastInteractive in runtimeEdges initialization * fix: import WorkflowInteractiveResponseType and handle lastInteractive as undefined in chatTest * feat: implement extractDeepestInteractive function and refactor usage in AIResponseBox and ChatBox utils * fix: refactor initWorkflowEdgeStatus and getWorkflowEntryNodeIds calls in dispatchRunAppNode for recovery handling * fix: ensure lastInteractive is handled consistently as undefined in runtimeEdges and runtimeNodes initialization * fix: update dispatchFormInput and dispatchUserSelect to use lastInteractive consistently * fix: update condition checks in dispatchFormInput and dispatchUserSelect to ensure lastInteractive type is validated correctly * fix: refactor dispatchRunAppNode to replace isRecovery with childrenInteractive for improved clarity in runtimeNodes and runtimeEdges initialization * refactor: streamline runtimeNodes and runtimeEdges initialization in dispatchRunAppNode for improved readability and maintainability * fix: update rewriteNodeOutputByHistories function to accept runtimeNodes and interactive as parameters for improved clarity * fix: simplify interactiveResponse assignment in dispatchWorkFlow for improved clarity * fix: update entryNodeIds check in getWorkflowEntryNodeIds to ensure it's an array for improved reliability * remove some invalid code --------- Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com> * update doc * update log * fix: update debug workflow to conditionally include nextStepSkipNodes… (#4511) * fix: update debug workflow to conditionally include nextStepSkipNodes based on lastInteractive for improved debugging accuracy * fix : type error * remove invalid code * fix: QA queue * fix: interactive * Test log (#4519) * add log (#4504) * add log * update log i18n * update log * delete template * add i18NT * add team operation log --------- Co-authored-by: gggaaallleee <91131304+gggaaallleee@users.noreply.github.com> * remove search * update doc --------- Co-authored-by: Theresa <63280168+sd0ric4@users.noreply.github.com> Co-authored-by: gggaaallleee <91131304+gggaaallleee@users.noreply.github.com>
This commit is contained in:
@@ -18,6 +18,7 @@ const MemberTable = dynamic(() => import('@/pageComponents/account/team/MemberTa
|
||||
const PermissionManage = dynamic(
|
||||
() => import('@/pageComponents/account/team/PermissionManage/index')
|
||||
);
|
||||
const OperationLogTable = dynamic(() => import('@/pageComponents/account/team/OperationLog/index'));
|
||||
const GroupManage = dynamic(() => import('@/pageComponents/account/team/GroupManage/index'));
|
||||
const OrgManage = dynamic(() => import('@/pageComponents/account/team/OrgManage/index'));
|
||||
const HandleInviteModal = dynamic(
|
||||
@@ -28,7 +29,8 @@ export enum TeamTabEnum {
|
||||
member = 'member',
|
||||
org = 'org',
|
||||
group = 'group',
|
||||
permission = 'permission'
|
||||
permission = 'permission',
|
||||
operationLog = 'operationLog'
|
||||
}
|
||||
|
||||
const Team = () => {
|
||||
@@ -57,7 +59,8 @@ const Team = () => {
|
||||
{ label: t('account_team:member'), value: TeamTabEnum.member },
|
||||
{ label: t('account_team:org'), value: TeamTabEnum.org },
|
||||
{ label: t('account_team:group'), value: TeamTabEnum.group },
|
||||
{ label: t('account_team:permission'), value: TeamTabEnum.permission }
|
||||
{ label: t('account_team:permission'), value: TeamTabEnum.permission },
|
||||
{ label: t('account_team:operation_log'), value: TeamTabEnum.operationLog }
|
||||
]}
|
||||
px={'1rem'}
|
||||
value={teamTab}
|
||||
@@ -150,6 +153,7 @@ const Team = () => {
|
||||
{teamTab === TeamTabEnum.org && <OrgManage Tabs={Tabs} />}
|
||||
{teamTab === TeamTabEnum.group && <GroupManage Tabs={Tabs} />}
|
||||
{teamTab === TeamTabEnum.permission && <PermissionManage Tabs={Tabs} />}
|
||||
{teamTab === TeamTabEnum.operationLog && <OperationLogTable Tabs={Tabs} />}
|
||||
</Box>
|
||||
</Flex>
|
||||
{invitelinkid && <HandleInviteModal invitelinkid={invitelinkid} />}
|
||||
|
||||
@@ -98,7 +98,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
const isPlugin = app.type === AppTypeEnum.plugin;
|
||||
|
||||
const userQuestion: UserChatItemType = (() => {
|
||||
const userQuestion: UserChatItemType = await (async () => {
|
||||
if (isPlugin) {
|
||||
return getPluginRunUserQuery({
|
||||
pluginInputs: getPluginInputsFromStoreNodes(app.modules),
|
||||
@@ -107,9 +107,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
});
|
||||
}
|
||||
|
||||
const latestHumanChat = chatMessages.pop() as UserChatItemType | undefined;
|
||||
const latestHumanChat = chatMessages.pop() as UserChatItemType;
|
||||
if (!latestHumanChat) {
|
||||
throw new Error('User question is empty');
|
||||
return Promise.reject('User question is empty');
|
||||
}
|
||||
return latestHumanChat;
|
||||
})();
|
||||
@@ -136,14 +136,14 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
const newHistories = concatHistories(histories, chatMessages);
|
||||
|
||||
const interactive = getLastInteractiveValue(newHistories) || undefined;
|
||||
// Get runtimeNodes
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, newHistories));
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, interactive));
|
||||
if (isPlugin) {
|
||||
runtimeNodes = updatePluginInputByVariables(runtimeNodes, variables);
|
||||
variables = {};
|
||||
}
|
||||
runtimeNodes = rewriteNodeOutputByHistories(newHistories, runtimeNodes);
|
||||
runtimeNodes = rewriteNodeOutputByHistories(runtimeNodes, interactive);
|
||||
|
||||
const workflowResponseWrite = getWorkflowResponseWrite({
|
||||
res,
|
||||
@@ -175,9 +175,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
runtimeNodes,
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, newHistories),
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, interactive),
|
||||
variables,
|
||||
query: removeEmptyUserInput(userQuestion.value),
|
||||
lastInteractive: interactive,
|
||||
chatConfig,
|
||||
histories: newHistories,
|
||||
stream: true,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { NextAPI } from '@/service/middleware/entry';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { defaultApp } from '@/web/core/app/constants';
|
||||
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
|
||||
import { getLastInteractiveValue } from '@fastgpt/global/core/workflow/runtime/utils';
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
@@ -44,6 +45,7 @@ async function handler(
|
||||
|
||||
// auth balance
|
||||
const { timezone, externalProvider } = await getUserChatInfoAndAuthTeamPoints(tmbId);
|
||||
const lastInteractive = getLastInteractiveValue(history);
|
||||
|
||||
/* start process */
|
||||
const { flowUsages, flowResponses, debugResponse, newVariables, workflowInteractiveResponse } =
|
||||
@@ -65,6 +67,7 @@ async function handler(
|
||||
},
|
||||
runtimeNodes: nodes,
|
||||
runtimeEdges: edges,
|
||||
lastInteractive,
|
||||
variables,
|
||||
query: query,
|
||||
chatConfig: defaultApp.chatConfig,
|
||||
|
||||
@@ -9,6 +9,8 @@ import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequency
|
||||
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
|
||||
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
|
||||
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { username, password } = req.body as PostLoginProps;
|
||||
@@ -64,6 +66,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
setCookie(res, token);
|
||||
|
||||
addOperationLog({
|
||||
tmbId: userDetail.team.tmbId,
|
||||
teamId: userDetail.team.teamId,
|
||||
event: OperationLogEventEnum.LOGIN
|
||||
});
|
||||
|
||||
return {
|
||||
user: userDetail,
|
||||
token
|
||||
|
||||
@@ -139,7 +139,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Computed start hook params
|
||||
const startHookText = (() => {
|
||||
// Chat
|
||||
const userQuestion = chatMessages[chatMessages.length - 1] as UserChatItemType | undefined;
|
||||
const userQuestion = chatMessages[chatMessages.length - 1] as UserChatItemType;
|
||||
if (userQuestion) return chatValue2RuntimePrompt(userQuestion.value).text;
|
||||
|
||||
// plugin
|
||||
@@ -245,16 +245,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
// Get chat histories
|
||||
const newHistories = concatHistories(histories, chatMessages);
|
||||
const interactive = getLastInteractiveValue(newHistories) || undefined;
|
||||
|
||||
// Get runtimeNodes
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, newHistories));
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, interactive));
|
||||
if (isPlugin) {
|
||||
// Assign values to runtimeNodes using variables
|
||||
runtimeNodes = updatePluginInputByVariables(runtimeNodes, variables);
|
||||
// Plugin runtime does not need global variables(It has been injected into the pluginInputNode)
|
||||
variables = {};
|
||||
}
|
||||
runtimeNodes = rewriteNodeOutputByHistories(newHistories, runtimeNodes);
|
||||
runtimeNodes = rewriteNodeOutputByHistories(runtimeNodes, interactive);
|
||||
|
||||
const workflowResponseWrite = getWorkflowResponseWrite({
|
||||
res,
|
||||
@@ -288,7 +289,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
runtimeNodes,
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, newHistories),
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, interactive),
|
||||
variables,
|
||||
query: removeEmptyUserInput(userQuestion.value),
|
||||
chatConfig,
|
||||
|
||||
@@ -139,7 +139,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Computed start hook params
|
||||
const startHookText = (() => {
|
||||
// Chat
|
||||
const userQuestion = chatMessages[chatMessages.length - 1] as UserChatItemType | undefined;
|
||||
const userQuestion = chatMessages[chatMessages.length - 1] as UserChatItemType;
|
||||
if (userQuestion) return chatValue2RuntimePrompt(userQuestion.value).text;
|
||||
|
||||
// plugin
|
||||
@@ -245,16 +245,16 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
// Get chat histories
|
||||
const newHistories = concatHistories(histories, chatMessages);
|
||||
|
||||
const interactive = getLastInteractiveValue(newHistories) || undefined;
|
||||
// Get runtimeNodes
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, newHistories));
|
||||
let runtimeNodes = storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes, interactive));
|
||||
if (isPlugin) {
|
||||
// Assign values to runtimeNodes using variables
|
||||
runtimeNodes = updatePluginInputByVariables(runtimeNodes, variables);
|
||||
// Plugin runtime does not need global variables(It has been injected into the pluginInputNode)
|
||||
variables = {};
|
||||
}
|
||||
runtimeNodes = rewriteNodeOutputByHistories(newHistories, runtimeNodes);
|
||||
runtimeNodes = rewriteNodeOutputByHistories(runtimeNodes, interactive);
|
||||
|
||||
const workflowResponseWrite = getWorkflowResponseWrite({
|
||||
res,
|
||||
@@ -288,9 +288,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
runtimeNodes,
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, newHistories),
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges, interactive),
|
||||
variables,
|
||||
query: removeEmptyUserInput(userQuestion.value),
|
||||
lastInteractive: interactive,
|
||||
chatConfig,
|
||||
histories: newHistories,
|
||||
stream,
|
||||
|
||||
Reference in New Issue
Block a user