V4.12.3 features (#5595)

* refactor: remove ModelProviderIdType and update related types (#5549)

* perf: model provider

* fix eval create split (#5570)

* git rebase --continuedoc

* add more variable types (#5540)

* variable types

* password

* time picker

* internal var

* file

* fix-test

* time select default value & range

* password & type render

* fix

* fix build

* fix

* move method

* split date select

* icon

* perf: variable code

* prompt editor add markdown plugin (#5556)

* editor markdown

* fix build

* pnpm lock

* add props

* update code

* fix list

* editor ui

* fix variable reset (#5586)

* perf: variables type code

* customize lexical indent (#5588)

* perf: multiple selector

* perf: tab plugin

* doc

* refactor: update workflow constants to use ToolTypeEnum (#5491)

* refactor: replace FlowNodeTemplateTypeEnum with string literals in workflow templates

* perf: tool type

---------

Co-authored-by: archer <545436317@qq.com>

* update doc

* fix: make table's row more natural while dragging it (#5596)

* feat: add APIGetTemplate function and refactor template fetching logic (#5498)

* feat: add APIGetTemplate function and refactor template fetching logic

* chore: adjust the code

* chore: update sdk

---------

Co-authored-by: FinleyGe <m13203533462@163.com>

* perf init system

* doc

* remove log

* remove i18n

* perf: variables render

---------

Co-authored-by: Ctrlz <143257420+ctrlz526@users.noreply.github.com>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: 伍闲犬 <whoeverimf5@gmail.com>
Co-authored-by: FinleyGe <m13203533462@163.com>
This commit is contained in:
Archer
2025-09-07 14:41:48 +08:00
committed by GitHub
parent c747fc03ad
commit 3f9b0fa1d4
166 changed files with 3407 additions and 11604 deletions

View File

@@ -4,21 +4,8 @@ import type { JsonSchemaPropertiesItemType } from '../app/jsonschema';
export enum FlowNodeTemplateTypeEnum {
systemInput = 'systemInput',
ai = 'ai',
function = 'function',
interactive = 'interactive',
// System tool type
tools = 'tools',
search = 'search',
multimodal = 'multimodal',
communication = 'communication',
finance = 'finance',
design = 'design',
productivity = 'productivity',
news = 'news',
entertainment = 'entertainment',
social = 'social',
scientific = 'scientific',
other = 'other',
// Team app type
@@ -332,53 +319,144 @@ export enum VariableInputEnum {
input = 'input',
textarea = 'textarea',
numberInput = 'numberInput',
JSONEditor = 'JSONEditor',
select = 'select',
custom = 'custom'
multipleSelect = 'multipleSelect',
timePointSelect = 'timePointSelect',
timeRangeSelect = 'timeRangeSelect',
switch = 'switch',
password = 'password',
file = 'file',
modelSelect = 'modelSelect',
datasetSelect = 'datasetSelect',
custom = 'custom',
internal = 'internal'
}
export const variableMap: Record<
VariableInputEnum,
{
icon: string;
label: string;
value: VariableInputEnum;
defaultValueType: WorkflowIOValueTypeEnum;
description?: string;
}
> = {
[VariableInputEnum.input]: {
icon: 'core/workflow/inputType/input',
label: i18nT('common:core.workflow.inputType.textInput'),
value: VariableInputEnum.input,
defaultValueType: WorkflowIOValueTypeEnum.string
},
type VariableConfigType = {
icon: string;
label: string;
value: VariableInputEnum;
defaultValueType: WorkflowIOValueTypeEnum;
description?: string;
};
export const variableConfigs: VariableConfigType[][] = [
[
{
icon: 'core/workflow/inputType/input',
label: i18nT('common:core.workflow.inputType.textInput'),
value: VariableInputEnum.input,
defaultValueType: WorkflowIOValueTypeEnum.string
},
{
icon: 'core/workflow/inputType/password',
label: i18nT('common:core.workflow.inputType.password'),
value: VariableInputEnum.password,
defaultValueType: WorkflowIOValueTypeEnum.string
},
{
icon: 'core/workflow/inputType/numberInput',
label: i18nT('common:core.workflow.inputType.number input'),
value: VariableInputEnum.numberInput,
defaultValueType: WorkflowIOValueTypeEnum.number
},
// {
// icon: 'core/workflow/inputType/jsonEditor',
// label: i18nT('common:core.workflow.inputType.jsonEditor'),
// value: VariableInputEnum.JSONEditor,
// defaultValueType: WorkflowIOValueTypeEnum.object
// },
{
icon: 'core/workflow/inputType/option',
label: i18nT('common:core.workflow.inputType.select'),
value: VariableInputEnum.select,
defaultValueType: WorkflowIOValueTypeEnum.string
},
{
icon: 'core/workflow/inputType/multipleSelect',
label: i18nT('common:core.workflow.inputType.multipleSelect'),
value: VariableInputEnum.multipleSelect,
defaultValueType: WorkflowIOValueTypeEnum.arrayString
},
{
icon: 'core/workflow/inputType/switch',
label: i18nT('common:core.workflow.inputType.switch'),
value: VariableInputEnum.switch,
defaultValueType: WorkflowIOValueTypeEnum.boolean
}
// {
// icon: 'core/workflow/inputType/timePointSelect',
// label: i18nT('common:core.workflow.inputType.timePointSelect'),
// value: VariableInputEnum.timePointSelect,
// defaultValueType: WorkflowIOValueTypeEnum.string
// },
// {
// icon: 'core/workflow/inputType/timeRangeSelect',
// label: i18nT('common:core.workflow.inputType.timeRangeSelect'),
// value: VariableInputEnum.timeRangeSelect,
// defaultValueType: WorkflowIOValueTypeEnum.arrayString
// }
// {
// icon: 'core/workflow/inputType/file',
// label: i18nT('common:core.workflow.inputType.file'),
// value: VariableInputEnum.file,
// defaultValueType: WorkflowIOValueTypeEnum.arrayString
// }
],
// [
// {
// icon: 'core/workflow/inputType/model',
// label: i18nT('common:core.workflow.inputType.modelSelect'),
// value: VariableInputEnum.modelSelect,
// defaultValueType: WorkflowIOValueTypeEnum.string
// },
// {
// icon: 'core/workflow/inputType/dataset',
// label: i18nT('common:core.workflow.inputType.datasetSelect'),
// value: VariableInputEnum.datasetSelect,
// defaultValueType: WorkflowIOValueTypeEnum.arrayString
// }
// ],
[
{
icon: 'core/workflow/inputType/external',
label: i18nT('common:core.workflow.inputType.custom'),
value: VariableInputEnum.custom,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.select type_desc')
},
{
icon: 'core/workflow/inputType/internal',
label: i18nT('common:core.workflow.inputType.internal'),
value: VariableInputEnum.internal,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.internal_type_desc')
}
]
];
export const variableMap: Record<VariableInputEnum, VariableConfigType> = {
...variableConfigs
.flat()
.reduce(
(acc, config) => ({ ...acc, [config.value]: config }),
{} as Record<VariableInputEnum, VariableConfigType>
),
[VariableInputEnum.textarea]: {
icon: 'core/workflow/inputType/textarea',
label: i18nT('common:core.workflow.inputType.textarea'),
value: VariableInputEnum.textarea,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.textarea_type_desc')
},
[VariableInputEnum.numberInput]: {
icon: 'core/workflow/inputType/numberInput',
label: i18nT('common:core.workflow.inputType.number input'),
value: VariableInputEnum.numberInput,
defaultValueType: WorkflowIOValueTypeEnum.number
},
[VariableInputEnum.select]: {
icon: 'core/workflow/inputType/option',
label: i18nT('common:core.workflow.inputType.select'),
value: VariableInputEnum.select,
defaultValueType: WorkflowIOValueTypeEnum.string
},
[VariableInputEnum.custom]: {
icon: 'core/workflow/inputType/customVariable',
label: i18nT('common:core.workflow.inputType.custom'),
value: VariableInputEnum.custom,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.select type_desc')
}
};
// Keep backward compatibility
export const variableMapGroups = variableConfigs;
/* run time */
export enum RuntimeEdgeStatusEnum {
'waiting' = 'waiting',

View File

@@ -30,7 +30,10 @@ export enum FlowNodeInputTypeEnum { // render ui
hidden = 'hidden',
custom = 'custom',
fileSelect = 'fileSelect'
fileSelect = 'fileSelect',
timePointSelect = 'timePointSelect',
timeRangeSelect = 'timeRangeSelect',
password = 'password'
}
export const FlowNodeInputMap: Record<
FlowNodeInputTypeEnum,
@@ -94,6 +97,15 @@ export const FlowNodeInputMap: Record<
},
[FlowNodeInputTypeEnum.fileSelect]: {
icon: 'core/workflow/inputType/file'
},
[FlowNodeInputTypeEnum.timePointSelect]: {
icon: 'core/workflow/inputType/timePointSelect'
},
[FlowNodeInputTypeEnum.timeRangeSelect]: {
icon: 'core/workflow/inputType/timeRangeSelect'
},
[FlowNodeInputTypeEnum.password]: {
icon: 'core/workflow/inputType/password'
}
};

View File

@@ -19,6 +19,7 @@ import type { FlowNodeOutputItemType, ReferenceValueType } from '../type/io';
import type { StoreNodeItemType } from '../type/node';
import { isValidReferenceValueFormat } from '../utils';
import type { RuntimeEdgeItemType, RuntimeNodeItemType } from './type';
import { isSecretValue } from '../../../common/secret/utils';
export const checkIsBranchNode = (node: RuntimeNodeItemType) => {
if (node.catchError) return true;
@@ -67,7 +68,7 @@ export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number
};
/* value type format */
export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
export const valueTypeFormat = (value: any, valueType?: WorkflowIOValueTypeEnum) => {
const isObjectString = (value: any) => {
if (typeof value === 'string' && value !== 'false' && value !== 'true') {
const trimmedValue = value.trim();
@@ -81,34 +82,37 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
// 1. any值忽略格式化
if (value === undefined || value === null) return value;
if (!type || type === WorkflowIOValueTypeEnum.any) return value;
if (!valueType || valueType === WorkflowIOValueTypeEnum.any) return value;
// Password check
if (valueType === WorkflowIOValueTypeEnum.string && isSecretValue(value)) return value;
// 2. 如果值已经符合目标类型,直接返回
if (
(type === WorkflowIOValueTypeEnum.string && typeof value === 'string') ||
(type === WorkflowIOValueTypeEnum.number && typeof value === 'number') ||
(type === WorkflowIOValueTypeEnum.boolean && typeof value === 'boolean') ||
(type.startsWith('array') && Array.isArray(value)) ||
(type === WorkflowIOValueTypeEnum.object && typeof value === 'object') ||
(type === WorkflowIOValueTypeEnum.chatHistory &&
(valueType === WorkflowIOValueTypeEnum.string && typeof value === 'string') ||
(valueType === WorkflowIOValueTypeEnum.number && typeof value === 'number') ||
(valueType === WorkflowIOValueTypeEnum.boolean && typeof value === 'boolean') ||
(valueType.startsWith('array') && Array.isArray(value)) ||
(valueType === WorkflowIOValueTypeEnum.object && typeof value === 'object') ||
(valueType === WorkflowIOValueTypeEnum.chatHistory &&
(Array.isArray(value) || typeof value === 'number')) ||
(type === WorkflowIOValueTypeEnum.datasetQuote && Array.isArray(value)) ||
(type === WorkflowIOValueTypeEnum.selectDataset && Array.isArray(value)) ||
(type === WorkflowIOValueTypeEnum.selectApp && typeof value === 'object')
(valueType === WorkflowIOValueTypeEnum.datasetQuote && Array.isArray(value)) ||
(valueType === WorkflowIOValueTypeEnum.selectDataset && Array.isArray(value)) ||
(valueType === WorkflowIOValueTypeEnum.selectApp && typeof value === 'object')
) {
return value;
}
// 4. 按目标类型,进行格式转化
// 4.1 基本类型转换
if (type === WorkflowIOValueTypeEnum.string) {
if (valueType === WorkflowIOValueTypeEnum.string) {
return typeof value === 'object' ? JSON.stringify(value) : String(value);
}
if (type === WorkflowIOValueTypeEnum.number) {
if (valueType === WorkflowIOValueTypeEnum.number) {
if (value === '') return undefined;
return Number(value);
}
if (type === WorkflowIOValueTypeEnum.boolean) {
if (valueType === WorkflowIOValueTypeEnum.boolean) {
if (typeof value === 'string') {
return value.toLowerCase() === 'true';
}
@@ -116,7 +120,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
}
// 4.3 字符串转对象
if (type === WorkflowIOValueTypeEnum.object) {
if (valueType === WorkflowIOValueTypeEnum.object) {
if (isObjectString(value)) {
const trimmedValue = value.trim();
try {
@@ -127,7 +131,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
}
// 4.4 数组类型(这里 value 不是数组类型)TODO: 嵌套数据类型转化)
if (type.startsWith('array')) {
if (valueType.startsWith('array')) {
if (isObjectString(value)) {
try {
return json5.parse(value);
@@ -142,7 +146,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
WorkflowIOValueTypeEnum.datasetQuote,
WorkflowIOValueTypeEnum.selectDataset,
WorkflowIOValueTypeEnum.selectApp
].includes(type)
].includes(valueType)
) {
if (isObjectString(value)) {
try {
@@ -153,7 +157,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
}
// Invalid history type
if (type === WorkflowIOValueTypeEnum.chatHistory) {
if (valueType === WorkflowIOValueTypeEnum.chatHistory) {
if (isObjectString(value)) {
try {
return json5.parse(value);

View File

@@ -2,8 +2,8 @@ import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { i18nT } from '../../../../../web/i18n/utils';

View File

@@ -8,8 +8,8 @@ import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
ContentTypes
ContentTypes,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';

View File

@@ -7,8 +7,8 @@ import { type FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { i18nT } from '../../../../../web/i18n/utils';

View File

@@ -18,7 +18,6 @@ import {
type ReferenceArrayValueType,
type ReferenceItemValueType
} from './type/io.d';
import type { NodeToolConfigType } from './type/node';
import { type StoreNodeItemType } from './type/node';
import type {
VariableItemType,
@@ -247,7 +246,7 @@ export const appData2FlowNodeIO = ({
const variableInput = !chatConfig?.variables
? []
: chatConfig.variables.map((item) => {
const renderTypeMap = {
const renderTypeMap: Record<VariableInputEnum, FlowNodeInputTypeEnum[]> = {
[VariableInputEnum.input]: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference],
[VariableInputEnum.textarea]: [
FlowNodeInputTypeEnum.textarea,
@@ -255,16 +254,22 @@ export const appData2FlowNodeIO = ({
],
[VariableInputEnum.numberInput]: [FlowNodeInputTypeEnum.numberInput],
[VariableInputEnum.select]: [FlowNodeInputTypeEnum.select],
[VariableInputEnum.custom]: [
FlowNodeInputTypeEnum.input,
FlowNodeInputTypeEnum.reference
],
default: [FlowNodeInputTypeEnum.reference]
[VariableInputEnum.multipleSelect]: [FlowNodeInputTypeEnum.multipleSelect],
[VariableInputEnum.JSONEditor]: [FlowNodeInputTypeEnum.JSONEditor],
[VariableInputEnum.timePointSelect]: [FlowNodeInputTypeEnum.timePointSelect],
[VariableInputEnum.timeRangeSelect]: [FlowNodeInputTypeEnum.timeRangeSelect],
[VariableInputEnum.switch]: [FlowNodeInputTypeEnum.switch],
[VariableInputEnum.password]: [FlowNodeInputTypeEnum.password],
[VariableInputEnum.file]: [FlowNodeInputTypeEnum.fileSelect],
[VariableInputEnum.modelSelect]: [FlowNodeInputTypeEnum.selectLLMModel],
[VariableInputEnum.datasetSelect]: [FlowNodeInputTypeEnum.selectDataset],
[VariableInputEnum.internal]: [FlowNodeInputTypeEnum.hidden],
[VariableInputEnum.custom]: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference]
};
return {
key: item.key,
renderTypeList: renderTypeMap[item.type] || renderTypeMap.default,
renderTypeList: renderTypeMap[item.type] || [FlowNodeInputTypeEnum.reference],
label: item.label,
debugLabel: item.label,
description: '',