V4.11.0 features (#5270)

* feat: workflow catch error (#5220)

* feat: error catch

* feat: workflow catch error

* perf: add catch error to node

* feat: system tool error catch

* catch error

* fix: ts

* update doc

* perf: training queue code (#5232)

* doc

* perf: training queue code

* Feat: 优化错误提示与重试逻辑 (#5192)

* feat: 批量重试异常数据 & 报错信息国际化

  - 新增“全部重试”按钮,支持批量重试所有训练异常数据
  - 报错信息支持国际化,常见错误自动映射为 i18n key
  - 相关文档和 i18n 资源已同步更新

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism

* feat: add retry_failed i18n key

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism

* feat: enhance error message and retry mechanism : 5

* feat: enhance error message and retry mechanism : 6

* feat: enhance error message and retry mechanism : 7

* feat: enhance error message and retry mechanism : 8

* perf: catch chat error

* perf: copy hook (#5246)

* perf: copy hook

* doc

* doc

* add app evaluation (#5083)

* add app evaluation

* fix

* usage

* variables

* editing condition

* var ui

* isplus filter

* migrate code

* remove utils

* name

* update type

* build

* fix

* fix

* fix

* delete comment

* fix

* perf: eval code

* eval code

* eval code

* feat: ttfb time in model log

* Refactor chat page (#5253)

* feat: update side bar layout; add login and logout logic at chat page

* refactor: encapsulate login logic and reuse it in `LoginModal` and `Login` page

* chore: improve some logics and comments

* chore: improve some logics

* chore: remove redundant side effect; add translations

---------

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

* perf: chat page code

* doc

* perf: provider redirect

* chore: ui improvement (#5266)

* Fix: SSE

* Fix: SSE

* eval pagination (#5264)

* eval scroll pagination

* change eval list to manual pagination

* number

* fix build

* fix

* version doc (#5267)

* version doc

* version doc

* doc

* feat: eval model select

* config eval model

* perf: eval detail modal ui

* doc

* doc

* fix: chat store reload

* doc

---------

Co-authored-by: colnii <1286949794@qq.com>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: 酒川户 <76519998+chuanhu9@users.noreply.github.com>
This commit is contained in:
Archer
2025-07-22 09:42:50 +08:00
committed by GitHub
parent de208d6c3f
commit 13b7e0a192
212 changed files with 5840 additions and 3400 deletions

View File

@@ -269,11 +269,11 @@ export enum NodeOutputKeyEnum {
reasoningText = 'reasoningText', // node reasoning. the value will be show but not save to history
success = 'success',
failed = 'failed',
error = 'error',
text = 'system_text',
addOutputParam = 'system_addOutputParam',
rawResponse = 'system_rawResponse',
systemError = 'system_error',
errorText = 'system_error_text',
// start
userFiles = 'userFiles',
@@ -312,7 +312,13 @@ export enum NodeOutputKeyEnum {
loopStartIndex = 'loopStartIndex',
// form input
formInputResult = 'formInputResult'
formInputResult = 'formInputResult',
// File
fileTitle = 'fileTitle',
// @deprecated
error = 'error'
}
export enum VariableInputEnum {

View File

@@ -99,6 +99,7 @@ export const FlowNodeInputMap: Record<
export enum FlowNodeOutputTypeEnum {
hidden = 'hidden',
error = 'error',
source = 'source',
static = 'static',
dynamic = 'dynamic'

View File

@@ -9,7 +9,7 @@ import type { FlowNodeInputItemType, FlowNodeOutputItemType } from '../type/io.d
import type { NodeToolConfigType, StoreNodeItemType } from '../type/node';
import type { DispatchNodeResponseKeyEnum } from './constants';
import type { StoreEdgeItemType } from '../type/edge';
import type { NodeInputKeyEnum } from '../constants';
import type { NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import type { ClassifyQuestionAgentItemType } from '../template/system/classifyQuestion/type';
import type { NextApiResponse } from 'next';
import { UserModelSchema } from '../../../support/user/type';
@@ -24,7 +24,10 @@ import type { AiChatQuoteRoleType } from '../template/system/aiChat/type';
import type { OpenaiAccountType } from '../../../support/user/team/type';
import { LafAccountType } from '../../../support/user/team/type';
import type { CompletionFinishReason } from '../../ai/type';
import type { WorkflowInteractiveResponseType } from '../template/system/interactive/type';
import type {
InteractiveNodeResponseType,
WorkflowInteractiveResponseType
} from '../template/system/interactive/type';
import type { SearchDataResponseItemType } from '../../dataset/type';
export type ExternalProviderType = {
openaiAccount?: OpenaiAccountType;
@@ -104,6 +107,9 @@ export type RuntimeNodeItemType = {
// Tool
toolConfig?: StoreNodeItemType['toolConfig'];
// catch error
catchError?: boolean;
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {
@@ -116,7 +122,12 @@ export type DispatchNodeResponseType = {
runningTime?: number;
query?: string;
textOutput?: string;
// Client will toast
error?: Record<string, any> | string;
// Just show
errorText?: string;
customInputs?: Record<string, any>;
customOutputs?: Record<string, any>;
nodeInputs?: Record<string, any>;
@@ -235,7 +246,7 @@ export type DispatchNodeResponseType = {
extensionTokens?: number;
};
export type DispatchNodeResultType<T = {}> = {
export type DispatchNodeResultType<T = {}, ERR = { [NodeOutputKeyEnum.errorText]?: string }> = {
[DispatchNodeResponseKeyEnum.skipHandleId]?: string[]; // skip some edge handle id
[DispatchNodeResponseKeyEnum.nodeResponse]?: DispatchNodeResponseType; // The node response detail
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; // Node total usage
@@ -246,7 +257,11 @@ export type DispatchNodeResultType<T = {}> = {
[DispatchNodeResponseKeyEnum.runTimes]?: number;
[DispatchNodeResponseKeyEnum.newVariables]?: Record<string, any>;
[DispatchNodeResponseKeyEnum.memories]?: Record<string, any>;
} & T;
[DispatchNodeResponseKeyEnum.interactive]?: InteractiveNodeResponseType;
data?: T;
error?: ERR;
};
/* Single node props */
export type AIChatNodeProps = {

View File

@@ -251,7 +251,8 @@ export const storeNodes2RuntimeNodes = (
outputs: node.outputs,
pluginId: node.pluginId,
version: node.version,
toolConfig: node.toolConfig
toolConfig: node.toolConfig,
catchError: node.catchError
};
}) || []
);

View File

@@ -2,6 +2,7 @@ import type { FlowNodeOutputItemType } from '../type/io.d';
import { NodeOutputKeyEnum } from '../constants';
import { FlowNodeOutputTypeEnum } from '../node/constant';
import { WorkflowIOValueTypeEnum } from '../constants';
import { i18nT } from '../../../../web/i18n/utils';
export const Output_Template_AddOutput: FlowNodeOutputItemType = {
id: NodeOutputKeyEnum.addOutputParam,
@@ -15,3 +16,11 @@ export const Output_Template_AddOutput: FlowNodeOutputItemType = {
showDefaultValue: false
}
};
export const Output_Template_Error_Message: FlowNodeOutputItemType = {
id: NodeOutputKeyEnum.errorText,
key: NodeOutputKeyEnum.errorText,
type: FlowNodeOutputTypeEnum.error,
valueType: WorkflowIOValueTypeEnum.string,
label: i18nT('workflow:error_text')
};

View File

@@ -20,6 +20,7 @@ import { chatNodeSystemPromptTip, systemPromptTip } from '../tip';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { i18nT } from '../../../../../web/i18n/utils';
import { Input_Template_File_Link } from '../input';
import { Output_Template_Error_Message } from '../output';
export const AgentNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.agent,
@@ -31,6 +32,7 @@ export const AgentNode: FlowNodeTemplateType = {
name: i18nT('workflow:template.agent'),
intro: i18nT('workflow:template.agent_intro'),
showStatus: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/tool/',
version: '4.9.2',
inputs: [
@@ -107,6 +109,7 @@ export const AgentNode: FlowNodeTemplateType = {
description: i18nT('common:core.module.output.description.Ai response content'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
},
Output_Template_Error_Message
]
};

View File

@@ -20,6 +20,7 @@ import {
Input_Template_File_Link
} from '../../input';
import { i18nT } from '../../../../../../web/i18n/utils';
import { Output_Template_Error_Message } from '../../output';
export const AiChatQuoteRole = {
key: NodeInputKeyEnum.aiChatQuoteRole,
@@ -54,6 +55,7 @@ export const AiChatModule: FlowNodeTemplateType = {
isTool: true,
courseUrl: '/docs/guide/dashboard/workflow/ai_chat/',
version: '4.9.7',
catchError: false,
inputs: [
Input_Template_SettingAiModel,
// --- settings modal
@@ -158,6 +160,7 @@ export const AiChatModule: FlowNodeTemplateType = {
const modelItem = llmModelList.find((item) => item.model === model);
return modelItem?.reasoning !== true;
}
}
},
Output_Template_Error_Message
]
};

View File

@@ -13,6 +13,7 @@ import {
import { Input_Template_SelectAIModel, Input_Template_History } from '../../input';
import { LLMModelTypeEnum } from '../../../../ai/constants';
import { i18nT } from '../../../../../../web/i18n/utils';
import { Output_Template_Error_Message } from '../../output';
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
@@ -25,6 +26,7 @@ export const ContextExtractModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_text_content_extraction'),
showStatus: true,
isTool: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/content_extract/',
version: '4.9.2',
inputs: [
@@ -76,6 +78,7 @@ export const ContextExtractModule: FlowNodeTemplateType = {
description: i18nT('workflow:complete_extraction_result_description'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
},
Output_Template_Error_Message
]
};

View File

@@ -15,6 +15,7 @@ import {
import { Input_Template_UserChatInput } from '../input';
import { DatasetSearchModeEnum } from '../../../dataset/constants';
import { i18nT } from '../../../../../web/i18n/utils';
import { Output_Template_Error_Message } from '../output';
export const Dataset_SEARCH_DESC = i18nT('workflow:template.dataset_search_intro');
@@ -29,6 +30,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
intro: Dataset_SEARCH_DESC,
showStatus: true,
isTool: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/dataset_search/',
version: '4.9.2',
inputs: [
@@ -143,6 +145,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.datasetQuote,
valueDesc: datasetQuoteValueDesc
}
},
Output_Template_Error_Message
]
};

View File

@@ -26,6 +26,7 @@ export const HttpNode468: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_http_request'),
showStatus: true,
isTool: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/http/',
inputs: [
{
@@ -123,14 +124,6 @@ export const HttpNode468: FlowNodeTemplateType = {
label: i18nT('workflow:http_extract_output'),
description: i18nT('workflow:http_extract_output_description')
},
{
id: NodeOutputKeyEnum.error,
key: NodeOutputKeyEnum.error,
label: i18nT('workflow:request_error'),
description: i18nT('workflow:http_request_error_info'),
valueType: WorkflowIOValueTypeEnum.object,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.httpRawResponse,
key: NodeOutputKeyEnum.httpRawResponse,
@@ -139,6 +132,13 @@ export const HttpNode468: FlowNodeTemplateType = {
description: i18nT('workflow:http_raw_response_description'),
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.error,
key: NodeOutputKeyEnum.error,
label: i18nT('workflow:error_text'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.error
}
]
};

View File

@@ -11,7 +11,7 @@ import {
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { Output_Template_AddOutput, Output_Template_Error_Message } from '../output';
import { i18nT } from '../../../../../web/i18n/utils';
export const nodeLafCustomInputConfig = {
@@ -31,6 +31,7 @@ export const LafModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_laf_function_call'),
showStatus: true,
isTool: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/laf/',
inputs: [
{
@@ -57,8 +58,7 @@ export const LafModule: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.static
},
{
...Output_Template_AddOutput
}
Output_Template_AddOutput,
Output_Template_Error_Message
]
};

View File

@@ -11,6 +11,7 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { Output_Template_Error_Message } from '../../output';
export const ReadFilesNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.readFiles,
@@ -43,6 +44,7 @@ export const ReadFilesNode: FlowNodeTemplateType = {
description: i18nT('app:workflow.read_files_result_desc'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
}
},
Output_Template_Error_Message
]
};

View File

@@ -25,6 +25,7 @@ export const CodeNode: FlowNodeTemplateType = {
name: i18nT('workflow:code_execution'),
intro: i18nT('workflow:execute_a_simple_script_code_usually_for_complex_data_processing'),
showStatus: true,
catchError: false,
courseUrl: '/docs/guide/dashboard/workflow/sandbox/',
inputs: [
{
@@ -89,14 +90,6 @@ export const CodeNode: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.object,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.error,
key: NodeOutputKeyEnum.error,
label: i18nT('workflow:execution_error'),
description: i18nT('workflow:error_info_returns_empty_on_success'),
valueType: WorkflowIOValueTypeEnum.object,
type: FlowNodeOutputTypeEnum.static
},
{
id: 'qLUQfhG0ILRX',
type: FlowNodeOutputTypeEnum.dynamic,
@@ -110,6 +103,13 @@ export const CodeNode: FlowNodeTemplateType = {
key: 'data2',
valueType: WorkflowIOValueTypeEnum.string,
label: 'data2'
},
{
id: NodeOutputKeyEnum.error,
key: NodeOutputKeyEnum.error,
label: i18nT('workflow:error_text'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.error
}
]
};

View File

@@ -48,6 +48,7 @@ export type FlowNodeCommonType = {
isLatestVersion?: boolean; // Just ui show
// data
catchError?: boolean;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];

View File

@@ -52,7 +52,11 @@ import { ChatRoleEnum } from '../../core/chat/constants';
import { runtimePrompt2ChatsValue } from '../../core/chat/adapt';
import { getPluginRunContent } from '../../core/app/plugin/utils';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
export const getHandleId = (
nodeId: string,
type: 'source' | 'source_catch' | 'target',
key: string
) => {
return `${nodeId}-${type}-${key}`;
};
@@ -219,16 +223,14 @@ export const pluginData2FlowNodeIO = ({
]
: [],
outputs: pluginOutput
? [
...pluginOutput.inputs.map((item) => ({
id: item.key,
type: FlowNodeOutputTypeEnum.static,
key: item.key,
valueType: item.valueType,
label: item.label || item.key,
description: item.description
}))
]
? pluginOutput.inputs.map((item) => ({
id: item.key,
type: FlowNodeOutputTypeEnum.static,
key: item.key,
valueType: item.valueType,
label: item.label || item.key,
description: item.description
}))
: []
};
};