App run node update (#2542)

* feat(workflow): allow apps to be invoked like plugins (#2521)

* feat(workflow): allow apps to be invoked like plugins

* fix type

* Encapsulate SSE response methods (#2530)

* perf: sse response fn

* perf: sse response

* fix: ts

* perf: not ssl copy

* perf: myselect auto scroll

* perf: run app code

* fix: app plugin (#2538)

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2024-08-27 16:43:19 +08:00
committed by GitHub
parent 67445b40bc
commit 450167c951
67 changed files with 706 additions and 4899 deletions

View File

@@ -128,6 +128,7 @@ export enum NodeInputKeyEnum {
// read files
fileUrlList = 'fileUrlList',
// user select
userSelectOptions = 'userSelectOptions'
}

View File

@@ -106,6 +106,7 @@ export enum FlowNodeTypeEnum {
contentExtract = 'contentExtract',
httpRequest468 = 'httpRequest468',
runApp = 'app',
appModule = 'appModule',
pluginModule = 'pluginModule',
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput',

View File

@@ -19,6 +19,7 @@ import { RuntimeNodeItemType } from '../runtime/type';
import { RuntimeEdgeItemType } from './edge';
import { ReadFileNodeResponse } from '../template/system/readFiles/type';
import { UserSelectOptionType } from '../template/system/userSelect/type';
import { WorkflowResponseType } from '../../../../service/core/workflow/dispatch/type';
/* workflow props */
export type ChatDispatchProps = {
@@ -36,9 +37,9 @@ export type ChatDispatchProps = {
query: UserChatItemValueItemType[]; // trigger query
chatConfig: AppSchema['chatConfig'];
stream: boolean;
detail: boolean; // response detail
maxRunTimes: number;
isToolCall?: boolean;
workflowStreamResponse?: WorkflowResponseType;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {

View File

@@ -236,7 +236,7 @@ export const textAdaptGptResponse = ({
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
return JSON.stringify({
return {
...extraData,
id: '',
object: '',
@@ -252,7 +252,7 @@ export const textAdaptGptResponse = ({
finish_reason
}
]
});
};
};
/* Update runtimeNode's outputs with interactive data from history */

View File

@@ -16,6 +16,7 @@ import { RunAppModule } from './system/runApp/index';
import { PluginInputModule } from './system/pluginInput';
import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
import { RunAppPluginModule } from './system/runAppPlugin';
import { AiQueryExtension } from './system/queryExtension';
import type { FlowNodeTemplateType } from '../type/node';
@@ -44,8 +45,8 @@ const systemNodes: FlowNodeTemplateType[] = [
LafModule,
IfElseNode,
VariableUpdateNode,
CodeNode,
RunAppModule
CodeNode
// RunAppModule
];
/* app flow module templates */
export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
@@ -70,5 +71,6 @@ export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
)
),
EmptyNode,
RunPluginModule
RunPluginModule,
RunAppPluginModule
];

View File

@@ -73,3 +73,12 @@ export const Input_Template_Text_Quote: FlowNodeInputItemType = {
description: i18nT('app:document_quote_tip'),
valueType: WorkflowIOValueTypeEnum.string
};
export const Input_Template_File_Link: FlowNodeInputItemType = {
key: NodeInputKeyEnum.fileUrlList,
renderTypeList: [FlowNodeInputTypeEnum.reference],
required: true,
label: i18nT('app:workflow.user_file_input'),
debugLabel: i18nT('app:workflow.user_file_input'),
description: i18nT('app:workflow.user_file_input_desc'),
valueType: WorkflowIOValueTypeEnum.arrayString
};

View File

@@ -0,0 +1,19 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunAppPluginModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.appModule,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.appModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
intro: '',
name: '',
showStatus: false,
isTool: false,
version: '481',
inputs: [], // [{key:'pluginId'},...]
outputs: []
};

View File

@@ -22,5 +22,3 @@ type UserSelectInteractive = {
};
export type InteractiveNodeResponseItemType = InteractiveBasicType & UserSelectInteractive;
export type UserInteractiveType = UserSelectInteractive;

View File

@@ -1,10 +1,16 @@
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from './node/constant';
import {
chatHistoryValueDesc,
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from './node/constant';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
VariableInputEnum,
variableMap,
VARIABLE_NODE_ID
VARIABLE_NODE_ID,
NodeOutputKeyEnum
} from './constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType, ReferenceValueProps } from './type/io.d';
import { StoreNodeItemType } from './type/node';
@@ -25,6 +31,7 @@ import {
import { IfElseResultEnum } from './template/system/ifElse/constant';
import { RuntimeNodeItemType } from './runtime/type';
import { getReferenceVariableValue } from './runtime/utils';
import { Input_Template_History, Input_Template_UserChatInput } from './template/input';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`;
@@ -147,9 +154,11 @@ export const getModuleInputUiField = (input: FlowNodeInputItemType) => {
return {};
};
export const pluginData2FlowNodeIO = (
nodes: StoreNodeItemType[]
): {
export const pluginData2FlowNodeIO = ({
nodes
}: {
nodes: StoreNodeItemType[];
}): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} => {
@@ -180,6 +189,80 @@ export const pluginData2FlowNodeIO = (
};
};
export const appData2FlowNodeIO = ({
chatConfig
}: {
chatConfig?: AppChatConfigType;
}): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} => {
const variableInput = !chatConfig?.variables
? []
: chatConfig.variables.map((item) => {
const renderTypeMap = {
[VariableInputEnum.input]: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
[VariableInputEnum.textarea]: [
FlowNodeInputTypeEnum.textarea,
FlowNodeInputTypeEnum.reference
],
[VariableInputEnum.select]: [FlowNodeInputTypeEnum.select],
[VariableInputEnum.custom]: [
FlowNodeInputTypeEnum.input,
FlowNodeInputTypeEnum.reference
],
default: [FlowNodeInputTypeEnum.reference]
};
return {
key: item.key,
renderTypeList: renderTypeMap[item.type] || renderTypeMap.default,
label: item.label,
debugLabel: item.label,
description: '',
valueType: WorkflowIOValueTypeEnum.any,
required: item.required,
list: item.enums.map((enumItem) => ({
label: enumItem.value,
value: enumItem.value
}))
};
});
// const showFileLink =
// chatConfig?.fileSelectConfig?.canSelectFile || chatConfig?.fileSelectConfig?.canSelectImg;
return {
inputs: [
Input_Template_History,
Input_Template_UserChatInput,
// ...(showFileLink ? [Input_Template_File_Link] : []),
...variableInput
],
outputs: [
{
id: NodeOutputKeyEnum.history,
key: NodeOutputKeyEnum.history,
required: true,
label: 'core.module.output.label.New context',
description: 'core.module.output.description.New context',
valueType: WorkflowIOValueTypeEnum.chatHistory,
valueDesc: chatHistoryValueDesc,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.answerText,
key: NodeOutputKeyEnum.answerText,
required: false,
label: 'core.module.output.label.Ai response content',
description: 'core.module.output.description.Ai response content',
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
]
};
};
export const formatEditorVariablePickerIcon = (
variables: { key: string; label: string; type?: `${VariableInputEnum}`; required?: boolean }[]
): EditorVariablePickerType[] => {