chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -19,7 +19,7 @@ import { type IntelligenceType } from '@coze-arch/idl/intelligence_api';
|
||||
import { Emitter, type Event } from '@flowgram-adapter/common';
|
||||
|
||||
/**
|
||||
* chatflow testrun 选中的 item 信息
|
||||
* Chatflow testrun item info
|
||||
*/
|
||||
export interface SelectItem {
|
||||
name: string;
|
||||
|
||||
@@ -42,7 +42,7 @@ const STALE_TIME = 20000;
|
||||
|
||||
interface DatabaseNodeServiceState {
|
||||
/**
|
||||
* 数据库数据是否正在加载中
|
||||
* Is the database data loading?
|
||||
*/
|
||||
loading: boolean;
|
||||
|
||||
@@ -220,7 +220,7 @@ export class DatabaseNodeServiceImpl implements DatabaseNodeService {
|
||||
: undefined,
|
||||
operator
|
||||
? {
|
||||
// 对操作符的翻译前后端没有统一,所以这里暂时用 operation 代替
|
||||
// The translation of operators is not uniform, so operation is used here for the time being
|
||||
name: 'operation',
|
||||
input: {
|
||||
type: 'string',
|
||||
|
||||
@@ -19,9 +19,9 @@ import { type FlowNodeEntity } from '@flowgram-adapter/free-layout-editor';
|
||||
import { type ConditionOperator } from '@coze-workflow/base';
|
||||
export abstract class DatabaseNodeService {
|
||||
/**
|
||||
* 将数据库设置字段转换为数据库设置字段DTO。
|
||||
* @param name 数据库设置字段DTO的名称
|
||||
* @param value 整个表单数据
|
||||
* Converts a database settings field to a database settings field DTO.
|
||||
* @Param name Name of database settings field DTO
|
||||
* @Param value entire form data
|
||||
*/
|
||||
abstract convertSettingFieldToDTO(
|
||||
name: string,
|
||||
@@ -29,23 +29,23 @@ export abstract class DatabaseNodeService {
|
||||
node: FlowNodeEntity,
|
||||
): any;
|
||||
/**
|
||||
* 将数据库设置字段DTO转换为数据库设置字段。
|
||||
* @param name 数据库设置字段DTO的名称
|
||||
* @param value 整个表单数据
|
||||
* Converts the database settings field DTO to a database settings field.
|
||||
* @Param name Name of database settings field DTO
|
||||
* @Param value entire form data
|
||||
*/
|
||||
abstract convertSettingFieldDTOToField(name: string, value: any): any;
|
||||
/**
|
||||
* 将表单中的条件DTO转换为条件
|
||||
* @param name 条件DTO的名称
|
||||
* @param value 整个表单数据
|
||||
* Converts a conditional DTO in a form to a condition
|
||||
* @param name name of conditional DTO
|
||||
* @Param value entire form data
|
||||
*/
|
||||
abstract convertConditionDTOToCondition(name: string, value: any): any;
|
||||
|
||||
/**
|
||||
* 将条件逻辑DTO转换为条件逻辑。
|
||||
* @param name 条件逻辑DTO的名称
|
||||
* @param value 条件逻辑DTO的值
|
||||
* @returns value 整个表单数据
|
||||
* Converts conditional logic DTO to conditional logic.
|
||||
* @param name name of conditional logic DTO
|
||||
* @Param value The value of the conditional logic DTO
|
||||
* @Returns value of entire form data
|
||||
*/
|
||||
abstract convertConditionLogicDTOToConditionLogic(
|
||||
name: string,
|
||||
@@ -53,10 +53,10 @@ export abstract class DatabaseNodeService {
|
||||
): any;
|
||||
|
||||
/**
|
||||
* 将条件逻辑转换为条件逻辑DTO。
|
||||
* @param name 条件逻辑的名称
|
||||
* @param value 条件逻辑的值
|
||||
* @returns value 整个表单数据
|
||||
* Convert conditional logic to conditional logic DTO.
|
||||
* @param name name of conditional logic
|
||||
* @param value value of conditional logic
|
||||
* @Returns value of entire form data
|
||||
*/
|
||||
abstract convertConditionLogicToConditionLogicDTO(
|
||||
name: string,
|
||||
@@ -64,9 +64,9 @@ export abstract class DatabaseNodeService {
|
||||
): any;
|
||||
|
||||
/**
|
||||
* 将条件转换为条件DTO
|
||||
* @param name 条件的名称
|
||||
* @param value 整个表单数据
|
||||
* Convert Condition to Conditional DTO
|
||||
* @param name The name of the condition
|
||||
* @Param value entire form data
|
||||
*/
|
||||
abstract convertConditionToDTO(
|
||||
name: string,
|
||||
@@ -75,9 +75,9 @@ export abstract class DatabaseNodeService {
|
||||
): any;
|
||||
|
||||
/**
|
||||
* 判断当前条件是否不需要右值
|
||||
* @param condition 当前条件数据
|
||||
* @returns 如果条件不需要左值则返回true,否则返回false
|
||||
* Determine whether the current condition does not require an rvalue
|
||||
* @param condition Current condition data
|
||||
* @Returns true if the condition does not require an lvalue, false otherwise
|
||||
*/
|
||||
abstract checkConditionOperatorNoNeedRight(
|
||||
conditionOperator?: ConditionOperator,
|
||||
@@ -86,12 +86,12 @@ export abstract class DatabaseNodeService {
|
||||
abstract store: any;
|
||||
|
||||
/**
|
||||
* 查询当前数据库数据
|
||||
* Query the current database data
|
||||
*/
|
||||
abstract load(id: string): void;
|
||||
|
||||
/**
|
||||
* 清空数据库缓存的错误信息
|
||||
* Error messages for clearing the database cache
|
||||
*/
|
||||
abstract clearDatabaseError(id: string): void;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ import { WorkflowGlobalStateEntity } from '@/entities';
|
||||
interface NodeWithVersion {
|
||||
node: FlowNodeEntity;
|
||||
/**
|
||||
* 注意 version 可能是不存在的!!!
|
||||
* 1. 老数据
|
||||
* 2. 项目中的资源被移动到资源库
|
||||
* Note that the version may not exist!!!
|
||||
* 1. Old data
|
||||
* 2. Resources in the project are moved to the repository
|
||||
*/
|
||||
/**
|
||||
* 1. versionName: 形如 v0.0.1,是 wf 的版本索引,也是外显版本号
|
||||
* 2. versionTs: 字符串形式的时间戳,是 plugin 的版本索引,wf 无此概念
|
||||
* 1. versionName: In the form of v0.0.1, it is the version index of wf and the explicit version number
|
||||
* 2. versionTs: timestamp in the form of string, which is the version index of the plugin, wf has no such concept
|
||||
*/
|
||||
version?: string;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ export const getMyApiNodeName = (node: FlowNodeEntity) =>
|
||||
getMyApiNodeParam(node, 'apiName');
|
||||
|
||||
/**
|
||||
* 设置子流程节点的版本号
|
||||
* Set the version number of the subprocess node
|
||||
*/
|
||||
export const setSubWorkflowNodeVersion = (
|
||||
node: FlowNodeEntity,
|
||||
@@ -227,11 +227,11 @@ const setLLMApiFCVersion = (
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取插件节点的版本信息
|
||||
* Get the version information of the plug-in node
|
||||
*/
|
||||
export const getApiNodeVersion = (node: FlowNodeEntity) => {
|
||||
const nodeDataEntity = node.getData<WorkflowNodeData>(WorkflowNodeData);
|
||||
// 这里用了子流程的 type,实际上 api 也是相同
|
||||
// The type of subprocess is used here, and the api is actually the same.
|
||||
const nodeData = nodeDataEntity.getNodeData<StandardNodeType.Api>();
|
||||
return {
|
||||
latestVersionTs: nodeData.latestVersionTs,
|
||||
@@ -241,7 +241,7 @@ export const getApiNodeVersion = (node: FlowNodeEntity) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取子流程节点信息
|
||||
* Get subprocess node information
|
||||
*/
|
||||
export const getSubWorkflowNode = (node: FlowNodeEntity) => {
|
||||
const nodeDataEntity = node.getData<WorkflowNodeData>(WorkflowNodeData);
|
||||
@@ -257,7 +257,7 @@ export const recreateNodeForm = async (
|
||||
|
||||
const nodeRegistry = node.getNodeRegistry();
|
||||
|
||||
// 修改版本后,需要重新请求相应数据,因为相关数据的 key 都是带版本的,会取不到
|
||||
// After modifying the version, you need to rerequest the corresponding data, because the keys of the relevant data are all with versions and will not be retrieved.
|
||||
await nodeRegistry?.onInit?.({ data: formData.toJSON() }, context);
|
||||
|
||||
await formData.recreateForm(
|
||||
@@ -301,13 +301,13 @@ export class NodeVersionService {
|
||||
@inject(WorkflowPlaygroundContext) context: WorkflowPlaygroundContext;
|
||||
|
||||
/**
|
||||
* 遍历流程,获取流程中所有指定 workflowId 的子流程和对应的版本
|
||||
* Traverse the process and get all the subprocesses and corresponding versions of the specified workflowId in the process
|
||||
*/
|
||||
getSubWorkflowNodesWithVersion(workflowId: string) {
|
||||
const allNodes = this.document.getAllNodes();
|
||||
const nodesWithVersion: SubWorkflowNodeWithVersion[] = [];
|
||||
allNodes.forEach(node => {
|
||||
// 存在对应的子流程节点
|
||||
// There is a corresponding subprocess node
|
||||
if (
|
||||
isSubWorkflowNode(node) &&
|
||||
getMySubWorkflowNodeId(node) === workflowId
|
||||
@@ -319,7 +319,7 @@ export class NodeVersionService {
|
||||
});
|
||||
return;
|
||||
}
|
||||
// llm 节点需要下钻到技能中查看是否有引用对应的子流程
|
||||
// The llm node needs to drill down into the skill to see if there is a reference to the corresponding sub-process.
|
||||
if (isLLMNode(node)) {
|
||||
const wf = getLLMWorkflowFCById(node, workflowId);
|
||||
if (wf) {
|
||||
@@ -335,7 +335,7 @@ export class NodeVersionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历流程,获取流程中所有指定 pluginId 的节点和对应的版本
|
||||
* Traverse the process and get all the nodes and corresponding versions of the specified pluginId in the process
|
||||
*/
|
||||
getPluginNodesWithVersion(pluginId: string) {
|
||||
const allNodes = this.document.getAllNodes();
|
||||
@@ -425,15 +425,15 @@ export class NodeVersionService {
|
||||
|
||||
nodesCheck<T extends NodeWithVersion>(nodes: T[], targetVersion: string) {
|
||||
/**
|
||||
* 需要更新版本的节点有两种:
|
||||
* 1. 无版本号的节点
|
||||
* 2. 有版本号,但版本不一致的
|
||||
* There are two types of nodes that require an updated version:
|
||||
* 1. Node without version number
|
||||
* 2. There is a version number, but the versions are inconsistent
|
||||
*/
|
||||
const needUpdateNodes = nodes.filter(
|
||||
({ version }) => version !== targetVersion,
|
||||
);
|
||||
/**
|
||||
* 有版本号的节点更新版本属于有损的强制更新,需要统计出来提示用户。无版本号的节点是无损更新
|
||||
* The updated version of a node with a version number is a lossy forced update, and it needs to be counted to prompt the user. Nodes without a version number are lossless updates.
|
||||
*/
|
||||
const needForceNodes = needUpdateNodes.filter(({ version }) => !!version);
|
||||
const needUpdate = !!needUpdateNodes.length;
|
||||
@@ -447,13 +447,13 @@ export class NodeVersionService {
|
||||
}
|
||||
|
||||
async addSubWorkflowCheck(workflowId?: string, targetVersion?: string) {
|
||||
// 要添加的流程没有版本号,则跳过版本统一步骤
|
||||
// If the process to be added does not have a version number, skip the version unification step
|
||||
if (!targetVersion || !workflowId) {
|
||||
return true;
|
||||
}
|
||||
const sameNodesWithVersion =
|
||||
this.getSubWorkflowNodesWithVersion(workflowId);
|
||||
// 无同一个流程的节点
|
||||
// Nodes without the same process
|
||||
if (!sameNodesWithVersion.length) {
|
||||
return true;
|
||||
}
|
||||
@@ -474,8 +474,8 @@ export class NodeVersionService {
|
||||
|
||||
async addApiCheck(pluginId?: string, targetVersionTs?: string) {
|
||||
/**
|
||||
* 1. 版本号不存在,表示引用最新版本,直接跳过验证
|
||||
* 2. '0' 也视为最新版本,语意上等同于为空,也直接跳过验证
|
||||
* 1. The version number does not exist, which means that the latest version is referenced, and the verification is skipped directly.
|
||||
* 2. '0' is also regarded as the latest version, which is semantically equivalent to null and skips verification directly
|
||||
*/
|
||||
if (!pluginId || !targetVersionTs || targetVersionTs === '0') {
|
||||
return true;
|
||||
|
||||
@@ -32,17 +32,17 @@ import { WorkflowGlobalStateEntity } from '@/entities';
|
||||
|
||||
interface PluginNodeServiceState {
|
||||
/**
|
||||
* 插件节点数据是否正在加载中
|
||||
* Is the plug-in node data loading?
|
||||
*/
|
||||
loading: boolean;
|
||||
|
||||
/**
|
||||
* 插件节点数据,key 为插件具体工具的唯一标识,value 为插件节点数据
|
||||
* Plug-in node data, key is the unique identifier of the plug-in specific tool, and value is the plug-in node data.
|
||||
*/
|
||||
data: Record<string, ApiNodeDetailDTO>;
|
||||
|
||||
/**
|
||||
* 插件节点数据加载错误信息,key 为插件具体工具的唯一标识,value 为错误信息
|
||||
* Plug-in node data loading error message, key is the unique identifier of the plug-in specific tool, and value is the error message
|
||||
*/
|
||||
error: Record<string, string | undefined>;
|
||||
}
|
||||
@@ -153,8 +153,8 @@ export class PluginNodeService {
|
||||
identifier.api_id,
|
||||
projectId,
|
||||
],
|
||||
// 1. 设置 5s 缓存,保证一个流程内同请求只发送一次即可,不会产生过多性能劣化
|
||||
// 2. api detail 包含插件的输入输出、版本信息,数据有实时敏感性,不可数据滞后
|
||||
// 1. Set up a 5s cache to ensure that the same request is only sent once in a process, and there will be no excessive performance degradation.
|
||||
// 2. api detail contains the input and output, version information of the plug-in, the data has real-time sensitivity, and there is no data lag.
|
||||
staleTime: STALE_TIME,
|
||||
queryFn: async () =>
|
||||
await workflowApi.GetApiDetail(
|
||||
@@ -171,9 +171,9 @@ export class PluginNodeService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件状态检查,是否失效,判断 ApiNode 是否可用
|
||||
* @param params 参数
|
||||
* @returns 是否失效
|
||||
* Plugin status check, whether it is invalid, and determine whether ApiNode is available
|
||||
* @param params
|
||||
* Whether @returns is invalid
|
||||
*/
|
||||
isApiNodeDeprecated(params: {
|
||||
currentSpaceID: string;
|
||||
@@ -188,15 +188,15 @@ export class PluginNodeService {
|
||||
pluginProductUnlistType,
|
||||
} = params;
|
||||
|
||||
// 未下架
|
||||
// Not removed from the shelves
|
||||
if (pluginProductStatus !== PluginProductStatus.Unlisted) {
|
||||
return false;
|
||||
}
|
||||
// 被管理员下架
|
||||
// Removed by administrator
|
||||
if (pluginProductUnlistType === ProductUnlistType.ByAdmin) {
|
||||
return true;
|
||||
}
|
||||
// 被用户下架,但并不是当前插件的创建space
|
||||
// Removed by the user, but not the creation space of the current plugin
|
||||
if (
|
||||
pluginProductUnlistType === ProductUnlistType.ByUser &&
|
||||
currentSpaceID !== pluginSpaceID
|
||||
@@ -204,7 +204,7 @@ export class PluginNodeService {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 被用户下架,但处于插件创建space
|
||||
// Removed by the user, but in the plugin creation space
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -237,8 +237,8 @@ export class PluginNodeService {
|
||||
} else {
|
||||
this.state.setData(identifier, {
|
||||
...apiDetail,
|
||||
// 插件名称如果变更后(例如 getStock 修改成 getStock_v1),apiName 不会变还是 getStock,name 才是更新后的的 getStock_v1
|
||||
// 此时需要优先取 name 字段,否则 testrun 时会用老的 apiName,导致试运行不成功
|
||||
// If the plug-in name is changed (for example, getStock is changed to getStock_v1), apiName will not change or getStock, and name is the updated getStock_v1
|
||||
// At this time, the name field needs to be taken first, otherwise testrun will use the old apiName, resulting in unsuccessful practice run
|
||||
apiName: apiDetail.name || apiDetail.apiName,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export class RelatedCaseDataService {
|
||||
parentComponentID: this.globalState.workflowId,
|
||||
},
|
||||
caseName: undefined,
|
||||
pageLimit: 1, // 默认测试集数据只会在第一条
|
||||
pageLimit: 1, // Default test set data will only be in the first
|
||||
});
|
||||
|
||||
const defaultCaseData = caseData?.cases?.find(
|
||||
|
||||
@@ -27,19 +27,19 @@ const DEBOUNCE_TIME = 1000;
|
||||
|
||||
export interface RoleServiceState {
|
||||
/**
|
||||
* 是否首次加载完成
|
||||
* Is the first load complete?
|
||||
*/
|
||||
isReady: boolean;
|
||||
/**
|
||||
* 是否在加载角色配置
|
||||
* Is the role configuration loading?
|
||||
*/
|
||||
loading: boolean;
|
||||
/**
|
||||
* 是否在保存角色配置
|
||||
* Are you saving the role configuration?
|
||||
*/
|
||||
saving: boolean;
|
||||
/**
|
||||
* 角色配置数据
|
||||
* role configuration data
|
||||
*/
|
||||
data: ChatFlowRole | null;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ export class TestRunReporterService {
|
||||
|
||||
this.send(ReporterEventName.RunEnd, data);
|
||||
}
|
||||
/** form schema 生成速度上报 */
|
||||
/** Form schema generation speed report */
|
||||
formSchemaGen = {
|
||||
start: () => this.tracker.start(),
|
||||
end: (
|
||||
|
||||
@@ -67,7 +67,7 @@ export class ValueExpressionServiceImpl implements ValueExpressionService {
|
||||
return ValueExpressionUtils.isLiteral(value as ValueExpression);
|
||||
}
|
||||
|
||||
// 将 ValueExpression 转换为 ValueExpressionDTO
|
||||
// Convert ValueExpression to ValueExpressionDTO
|
||||
public toDTO(
|
||||
valueExpression?: ValueExpression,
|
||||
currentNode?: FlowNodeEntity,
|
||||
@@ -85,7 +85,7 @@ export class ValueExpressionServiceImpl implements ValueExpressionService {
|
||||
return dto;
|
||||
}
|
||||
|
||||
// 从 ValueExpressionDTO 生成 ValueExpression
|
||||
// Generating ValueExpression from ValueExpressionDTO
|
||||
public toVO(dto?: ValueExpressionDTO): ValueExpression | undefined {
|
||||
if (!dto) {
|
||||
return undefined;
|
||||
|
||||
@@ -23,38 +23,38 @@ import {
|
||||
|
||||
export abstract class ValueExpressionService {
|
||||
/**
|
||||
* 判断值是否为值表达式
|
||||
* @param value 值
|
||||
* @returns 是否为值表达式
|
||||
* Determine whether a value is a value expression
|
||||
* @param value
|
||||
* @Returns is a value expression
|
||||
*/
|
||||
abstract isValueExpression(value: unknown): boolean;
|
||||
|
||||
/**
|
||||
* 判断值是否为值表达式DTO
|
||||
* @param value 值
|
||||
* @returns 是否为值表达式DTO
|
||||
* Determine whether a value is a value expression DTO
|
||||
* @param value
|
||||
* @Returns is a value expression DTO
|
||||
*/
|
||||
abstract isValueExpressionDTO(value: unknown): boolean;
|
||||
|
||||
/**
|
||||
* 判断值是否为引用表达式
|
||||
* @param value 值
|
||||
* @returns 是否为引用表达式
|
||||
* Determine whether the value is a reference expression
|
||||
* @param value
|
||||
* @Returns is a reference expression
|
||||
*/
|
||||
abstract isRefExpression(value: unknown): boolean;
|
||||
|
||||
/**
|
||||
* 判断值是否为字面量表达式
|
||||
* @param value 值
|
||||
* @returns 是否为字面量表达式
|
||||
* Determine whether the value is a literal expression
|
||||
* @param value
|
||||
* @Returns is a literal expression
|
||||
*/
|
||||
abstract isLiteralExpression(value: RefExpression): boolean;
|
||||
|
||||
/**
|
||||
* 判断引用表达式变量是否存在
|
||||
* @param value 引用表达式
|
||||
* @param node 当前节点
|
||||
* @returns 是否存在
|
||||
* Determine whether a reference expression variable exists
|
||||
* @param value reference expression
|
||||
* @param node Current node
|
||||
* Does @returns exist
|
||||
*/
|
||||
abstract isRefExpressionVariableExists(
|
||||
value: RefExpression,
|
||||
@@ -62,10 +62,10 @@ export abstract class ValueExpressionService {
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* 将值表达式转换为DTO
|
||||
* @param valueExpression 值表达式
|
||||
* @param currentNode 当前节点
|
||||
* @returns 值表达式DTO
|
||||
* Convert value expressions to DTO
|
||||
* @param valueExpression
|
||||
* @param currentNode
|
||||
* @Returns value expression DTO
|
||||
*/
|
||||
abstract toDTO(
|
||||
valueExpression?: ValueExpression,
|
||||
@@ -73,9 +73,9 @@ export abstract class ValueExpressionService {
|
||||
): ValueExpressionDTO | undefined;
|
||||
|
||||
/**
|
||||
* 将值表达式DTO转换为值表达式
|
||||
* @param dto 值表达式DTO
|
||||
* @returns 值表达式
|
||||
* Converting a value expression DTO to a value expression
|
||||
* @param dto value expression DTO
|
||||
* @Returns value expression
|
||||
*/
|
||||
abstract toVO(dto?: ValueExpressionDTO): ValueExpression | undefined;
|
||||
}
|
||||
|
||||
@@ -78,10 +78,10 @@ export class WorkflowDependencyService {
|
||||
this.onSubWrokflowVersionChangeEmitter.event;
|
||||
|
||||
/**
|
||||
* 可能的 badcase:
|
||||
* - save 接口返回较慢,导致长链刷新先于版本冲突报错的刷新弹窗,但是该场景比较极限,后续有必要再优化
|
||||
* - canvas 接口返回较慢,导致长链消息推送了一条和当前版本一致的消息,导致一次额外刷新。
|
||||
* 通过刷新前再判断一次版本号,避免该问题。
|
||||
* Possible badcases:
|
||||
* - The save interface returns slowly, resulting in the refresh pop-up window of the long chain refresh before the version conflict error, but this scenario is relatively limited, and it is necessary to optimize it later.
|
||||
* - Canvas interface returns slowly, resulting in a long chain push notification message consistent with the current version, resulting in an additional refresh.
|
||||
* Avoid this problem by judging the version number again before refreshing.
|
||||
*/
|
||||
private workflowDocumentReload = debounce(
|
||||
(callback, messageVersion?: bigint) => {
|
||||
@@ -106,7 +106,7 @@ export class WorkflowDependencyService {
|
||||
n => n.flowNodeType === StandardNodeType.LLM,
|
||||
);
|
||||
|
||||
// LLM 节点技能更新
|
||||
// LLM Node Skill Update
|
||||
llmNodes?.forEach(node => {
|
||||
const formData = node.getData(FlowNodeFormData);
|
||||
const formValue = formData.toJSON();
|
||||
@@ -142,21 +142,21 @@ export class WorkflowDependencyService {
|
||||
) => Promise<void> | void;
|
||||
} = {
|
||||
[DependencySourceType.Workflow]: (_nodes, resource) => {
|
||||
// 当前工作流在其他页面被更新
|
||||
// The current workflow is updated on other pages
|
||||
if (resource?.resId === this.globalState.workflowId) {
|
||||
// 修改工作流名称或描述的情况 saveVersion 不会更新
|
||||
// If you modify the workflow name or description, saveVersion will not be updated
|
||||
const isMetaUpdate =
|
||||
resource?.operateType === MessageOperateType.MetaUpdate;
|
||||
// 切换工作流类型场景需要刷新
|
||||
// Switch workflow type scene needs to be refreshed
|
||||
const isFlowModeChange =
|
||||
resource?.extra?.flowMode !== undefined &&
|
||||
this.globalState.flowMode.toString() !== resource.extra.flowMode;
|
||||
const metaUpdateNeedRefresh = isMetaUpdate && isFlowModeChange;
|
||||
// 试运行过程中不需要刷新
|
||||
// No refresh required during practice runs
|
||||
const isTestRunning =
|
||||
this.testRunService.testRunState === TestRunState.Executing ||
|
||||
this.testRunService.testRunState === TestRunState.Paused;
|
||||
// 当前版本大于其他页面保存版本,不需要刷新
|
||||
// The current version is larger than the saved version of other pages and does not need to be refreshed.
|
||||
const resourceVersion = BigInt(resource?.saveVersion ?? 0);
|
||||
const isCurVersionNewer = saveVersion > resourceVersion;
|
||||
if (
|
||||
@@ -181,7 +181,7 @@ export class WorkflowDependencyService {
|
||||
const formData = node.getData(FlowNodeFormData);
|
||||
const formValue = formData.toJSON();
|
||||
const { workflowId } = formValue.inputs;
|
||||
// 当前工作流内子工作流被更新
|
||||
// The child workflows within the current workflow are updated
|
||||
if (resource?.resId === workflowId) {
|
||||
needUpdateNodeIds.push(workflowId);
|
||||
}
|
||||
@@ -225,7 +225,7 @@ export class WorkflowDependencyService {
|
||||
this.onDependencyChangeEmitter.fire(nextProps);
|
||||
},
|
||||
[DependencySourceType.DataSet]: (_, resource) => {
|
||||
// 清空知识库缓存
|
||||
// Clear the knowledge base cache
|
||||
this.globalState.sharedDataSetStore.clearDataSetInfosMap();
|
||||
this.onDependencyChangeEmitter.fire(resource);
|
||||
},
|
||||
@@ -238,7 +238,7 @@ export class WorkflowDependencyService {
|
||||
};
|
||||
|
||||
if (props?.bizType) {
|
||||
// 设置刷新弹窗中的刷新方法
|
||||
// Set the refresh method in the refresh pop-up window
|
||||
this.dependencyEntity.setRefreshFunc(() => {
|
||||
callback?.();
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
this.initState();
|
||||
this._toDispose.pushAll([this.cardDragEmitter]);
|
||||
}
|
||||
/** 开始拖拽 */
|
||||
/** Start dragging */
|
||||
public startDrag(dragNode: WorkflowCustomDragServiceState['dragNode']): void {
|
||||
const { isDragging, dragNode: oldDragNode } = this.state;
|
||||
if (isDragging && oldDragNode) {
|
||||
@@ -105,7 +105,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
json: dragNode?.json,
|
||||
});
|
||||
}
|
||||
/** 结束拖拽 */
|
||||
/** end drag */
|
||||
public endDrag() {
|
||||
const { isDragging, dragNode } = this.state;
|
||||
if (!isDragging && !dragNode?.type) {
|
||||
@@ -121,7 +121,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
json: dragNode?.json,
|
||||
});
|
||||
}
|
||||
/** 根据坐标判断是否可放置 */
|
||||
/** Determine whether it can be placed according to the coordinates */
|
||||
public canDrop(params: {
|
||||
coord: XYCoord;
|
||||
dragNode: WorkflowCustomDragServiceState['dragNode'];
|
||||
@@ -136,8 +136,8 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可放置到节点
|
||||
* NOTICE: 以下逻辑后续如果还有特化,需要考虑放到节点meta配置中
|
||||
* Can it be placed in the node?
|
||||
* NOTICE: If the following logic is still specialized in the future, it needs to be considered in the node meta configuration
|
||||
*/
|
||||
public canDropToNode(params: {
|
||||
dragNodeType?: StandardNodeType;
|
||||
@@ -154,14 +154,14 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
allowDrop: false,
|
||||
};
|
||||
}
|
||||
// 开始 / 结束节点不允许放入任何容器
|
||||
// Start/end nodes are not allowed to put in any containers
|
||||
if ([StandardNodeType.Start, StandardNodeType.End].includes(dragNodeType)) {
|
||||
return {
|
||||
allowDrop: false,
|
||||
dropNode,
|
||||
};
|
||||
}
|
||||
// Loop / Batch 节点不允许嵌套
|
||||
// Loop/Batch nodes do not allow nesting
|
||||
if (
|
||||
[StandardNodeType.Loop, StandardNodeType.Batch].includes(dragNodeType) &&
|
||||
dropNode?.getNodeMeta<WorkflowNodeMeta>().isContainer
|
||||
@@ -172,7 +172,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
dropNode,
|
||||
};
|
||||
}
|
||||
// Break节点与SetVariable节点仅能拖入Loop节点
|
||||
// Break nodes and SetVariable nodes can only be dragged into the Loop node
|
||||
if (
|
||||
[
|
||||
StandardNodeType.Break,
|
||||
@@ -199,7 +199,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
};
|
||||
}
|
||||
}
|
||||
// 放置节点为容器
|
||||
// Place a node as a container
|
||||
if (
|
||||
[FlowNodeBaseType.ROOT, FlowNodeBaseType.SUB_CANVAS].includes(
|
||||
dropNode.flowNodeType as FlowNodeBaseType,
|
||||
@@ -216,7 +216,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
};
|
||||
}
|
||||
|
||||
/** 是否可放置 */
|
||||
/** Can it be placed */
|
||||
public computeCanDrop(params: {
|
||||
coord: XYCoord;
|
||||
dragNode: WorkflowCustomDragServiceState['dragNode'];
|
||||
@@ -249,7 +249,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
dropNode,
|
||||
});
|
||||
}
|
||||
/** 初始化状态 */
|
||||
/** initialization state */
|
||||
private initState(): void {
|
||||
this.state = {
|
||||
isDragging: false,
|
||||
@@ -258,7 +258,7 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
dropNode: undefined,
|
||||
};
|
||||
}
|
||||
/** 获取重叠位置 */
|
||||
/** Get overlap position */
|
||||
private getCollisionTransform(params: {
|
||||
position: PositionSchema;
|
||||
dragNode: WorkflowCustomDragServiceState['dragNode'];
|
||||
@@ -278,12 +278,12 @@ export class WorkflowCustomDragService extends WorkflowDragService {
|
||||
bounds.width,
|
||||
bounds.height,
|
||||
);
|
||||
// 检测两个正方形是否相互碰撞
|
||||
// Check if two squares collide with each other
|
||||
return Rectangle.intersects(draggingRect, transformRect);
|
||||
});
|
||||
return collisionTransform;
|
||||
}
|
||||
/** 设置当前放置节点 */
|
||||
/** Set the current placement node */
|
||||
private setDropNode(newDropNode?: WorkflowNodeEntity) {
|
||||
this.state.dropNode = newDropNode;
|
||||
if (newDropNode) {
|
||||
|
||||
@@ -49,7 +49,7 @@ import { WorkflowFloatLayoutService } from './workflow-float-layout-service';
|
||||
import { WorkflowCustomDragService } from './workflow-drag-service';
|
||||
|
||||
/**
|
||||
* 调用画布编辑服务
|
||||
* Invoke the canvas editing service
|
||||
*/
|
||||
@injectable()
|
||||
export class WorkflowEditService {
|
||||
@@ -69,7 +69,7 @@ export class WorkflowEditService {
|
||||
protected context: WorkflowPlaygroundContext;
|
||||
|
||||
/**
|
||||
* 创建节点
|
||||
* Create Node
|
||||
* @param type
|
||||
* @param nodeJson
|
||||
* @param event
|
||||
@@ -96,13 +96,13 @@ export class WorkflowEditService {
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
// 异常处理
|
||||
// exception handling
|
||||
this.dragService.endDrag();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 节点初始化逻辑
|
||||
// node initialization logic
|
||||
const nodeV2Registry = getNodeV2Registry(type);
|
||||
await nodeV2Registry?.onInit?.(
|
||||
nodeJson as WorkflowNodeJSON,
|
||||
@@ -117,7 +117,7 @@ export class WorkflowEditService {
|
||||
}
|
||||
|
||||
if (isDrag) {
|
||||
// 拖拽生成节点
|
||||
// Drag and drop to generate nodes
|
||||
dragNode = await this.dragService.dropCard(
|
||||
type,
|
||||
event,
|
||||
@@ -125,7 +125,7 @@ export class WorkflowEditService {
|
||||
this.dragService.state.dropNode,
|
||||
);
|
||||
} else {
|
||||
// @deprecated 这里的逻辑目前跑不到这里来,后续可以考虑删掉
|
||||
// @Deprecated The logic here cannot run here at present, you can consider deleting it later.
|
||||
let position: IPoint;
|
||||
const nodeMeta =
|
||||
this.workflowDocument.getNodeRegister<WorkflowNodeRegistry>(type).meta;
|
||||
@@ -189,7 +189,7 @@ export class WorkflowEditService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制节点
|
||||
* copy node
|
||||
* @param node
|
||||
*/
|
||||
copyNode = async (node: WorkflowNodeEntity): Promise<WorkflowNodeEntity> => {
|
||||
@@ -217,7 +217,7 @@ export class WorkflowEditService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除线条
|
||||
* Delete lines
|
||||
*/
|
||||
deleteNode = (node: WorkflowNodeEntity, noConfirm?: boolean) => {
|
||||
if (noConfirm) {
|
||||
@@ -235,7 +235,7 @@ export class WorkflowEditService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 在销毁节点之前,运行节点自定义的 onDispose 方法
|
||||
* Before destroying the node, run the node's custom onDispose method
|
||||
* @param node
|
||||
*/
|
||||
private disposeNode(node: WorkflowNodeEntity) {
|
||||
@@ -255,11 +255,11 @@ export class WorkflowEditService {
|
||||
titleCache: string[] = [],
|
||||
shouldReplaceId = true,
|
||||
): WorkflowNodeJSON {
|
||||
// 覆写 ID
|
||||
// Override ID
|
||||
if (shouldReplaceId) {
|
||||
nodeJSON.id = this.nodesService.createUniqID();
|
||||
}
|
||||
// 覆写标题
|
||||
// Override title
|
||||
if (nodeJSON.data?.nodeMeta?.title) {
|
||||
set(
|
||||
nodeJSON,
|
||||
@@ -272,7 +272,7 @@ export class WorkflowEditService {
|
||||
);
|
||||
titleCache.push(nodeJSON.data.nodeMeta.title);
|
||||
}
|
||||
// 对子节点做递归处理
|
||||
// Recursive processing of sub-nodes
|
||||
if (nodeJSON.blocks) {
|
||||
nodeJSON.blocks = nodeJSON.blocks.map(n =>
|
||||
this.recreateNodeJSON(n, titleCache),
|
||||
@@ -281,7 +281,7 @@ export class WorkflowEditService {
|
||||
return nodeJSON;
|
||||
}
|
||||
|
||||
/** 选中节点,如果右侧浮动面板是节点表单,则切换节点 */
|
||||
/** Select the node and switch the node if the floating panel on the right is a node form */
|
||||
focusNode(node?: WorkflowNodeEntity): void {
|
||||
if (node) {
|
||||
this.selectService.selectNodeAndFocus(node);
|
||||
|
||||
@@ -85,14 +85,14 @@ export class WorkflowLinesService {
|
||||
|
||||
isError(fromId?: string, toId?: string): boolean {
|
||||
if (!fromId) {
|
||||
// 不允许无输入端口
|
||||
// No input port allowed
|
||||
return true;
|
||||
}
|
||||
|
||||
const line = this.getLine(fromId, toId);
|
||||
|
||||
if (!line) {
|
||||
// 输出不存在
|
||||
// Output does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ export class WorkflowLinesService {
|
||||
allLines.forEach(line => line.validate());
|
||||
}
|
||||
|
||||
// 将两个端口的连线进行交换
|
||||
// Swap the connection between the two ports
|
||||
replaceLineByPort(
|
||||
oldPortInfo: WorkflowLinePortInfo,
|
||||
newPortInfo: WorkflowLinePortInfo,
|
||||
@@ -130,16 +130,16 @@ export class WorkflowLinesService {
|
||||
line.info.fromPort === newPortInfo.fromPort,
|
||||
);
|
||||
|
||||
// 记录所有连线终点交集
|
||||
// Record the intersection of all connection endpoints
|
||||
const intersectionToPort = intersection(
|
||||
oldPortLines.map(line => line.toPort?.id),
|
||||
newPortLines.map(line => line.toPort?.id),
|
||||
);
|
||||
|
||||
oldPortLines
|
||||
// 若两条线的终点相同则放弃交换,
|
||||
// 1. 没必要交换,交换后的连线是相同的
|
||||
// 2. 过程中会生成两条相同连线,但是画布中不允许有两条相同连线,会导致一条连线丢失
|
||||
// If the ends of the two lines are the same, the exchange is abandoned.
|
||||
// 1. There is no need to exchange, the connection after the exchange is the same
|
||||
// 2. Two identical connections will be generated during the process, but two identical connections are not allowed in the canvas, which will cause one connection to be lost.
|
||||
.filter(
|
||||
line => !intersectionToPort.some(portId => portId === line.toPort?.id),
|
||||
)
|
||||
@@ -164,7 +164,7 @@ export class WorkflowLinesService {
|
||||
this.linesManager.forceUpdate();
|
||||
}
|
||||
|
||||
/** 监听拖拽空线条时 */
|
||||
/** Monitor when dragging an empty line */
|
||||
private onDragLineEnd(): Disposable {
|
||||
return this.dragService.onDragLineEnd(
|
||||
async (params: {
|
||||
|
||||
@@ -30,7 +30,7 @@ export class WorkflowModelsService {
|
||||
|
||||
protected models: Model[] = [];
|
||||
async load() {
|
||||
// TODO: 临时方案,模版空间为虚拟空间,只读模式不加载模型列表,解决权限问题
|
||||
// TODO: Temporary solution, the template space is virtual space, and the model list is not loaded in read-only mode to solve the permission problem
|
||||
if (
|
||||
this.globalState.readonly &&
|
||||
this.globalState.spaceId === PUBLIC_SPACE_ID
|
||||
@@ -51,15 +51,15 @@ export class WorkflowModelsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的COT模型
|
||||
* @returns 返回所有的COT模型
|
||||
* Acquire all COT models
|
||||
* @Returns all COT models
|
||||
*/
|
||||
getCoTModels() {
|
||||
return this.models.filter(model => model.model_ability?.cot_display);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是COT模型
|
||||
* Determine whether it is a COT model
|
||||
* @param modelType
|
||||
* @returns
|
||||
*/
|
||||
@@ -68,14 +68,14 @@ export class WorkflowModelsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是FunctionCall模型
|
||||
* Determine whether it is a FunctionCall model
|
||||
*/
|
||||
isFunctionCallModel(modelType: number): boolean {
|
||||
return !!this.getModelAbility(modelType)?.function_call;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型获取模型
|
||||
* Get the model by type
|
||||
* @param modelType
|
||||
* @returns
|
||||
*/
|
||||
@@ -84,7 +84,7 @@ export class WorkflowModelsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型能力
|
||||
* Acquire model capabilities
|
||||
* @param modelType
|
||||
* @returns
|
||||
*/
|
||||
|
||||
@@ -52,8 +52,8 @@ export const WorkflowOperationServiceProvider = Symbol(
|
||||
);
|
||||
|
||||
/**
|
||||
* workflow增删改查等操作接口调用
|
||||
* 由于多人协作和非多人模式存在两套不同接口,将判断逻辑统一收敛到这里, 减少脏代码入侵
|
||||
* Workflow addition, deletion, modification and other operation interface calls
|
||||
* Due to the existence of two different interfaces in multi-person collaboration and non-multiplayer modes, the judgment logic is uniformly converged here to reduce dirty code intrusion
|
||||
*/
|
||||
@injectable()
|
||||
export class WorkflowOperationService {
|
||||
@@ -90,9 +90,9 @@ export class WorkflowOperationService {
|
||||
const data = await workflowApi.PublishWorkflow({
|
||||
workflow_id: this.workflowId,
|
||||
space_id: this.spaceId,
|
||||
// 已废弃,待删除
|
||||
// Abandoned, to be deleted
|
||||
has_collaborator: false,
|
||||
// 发布都不经过 testrun 校验
|
||||
// Published without testrun verification
|
||||
force: true,
|
||||
...obj,
|
||||
});
|
||||
@@ -151,7 +151,7 @@ export class WorkflowOperationService {
|
||||
submit_commit_id: vcsData?.submit_commit_id || '',
|
||||
ignore_status_transfer: ignoreStatusTransfer,
|
||||
};
|
||||
// 仅 project 内需要
|
||||
// Required within the project only
|
||||
if (
|
||||
this.globalState.projectId &&
|
||||
FLAGS?.['bot.automation.project_multi_tab']
|
||||
@@ -160,7 +160,7 @@ export class WorkflowOperationService {
|
||||
}
|
||||
await workflowApi.SaveWorkflow(reqParams);
|
||||
if (this.globalState.projectId) {
|
||||
// 为了解决 canvas 接口获取 saveVersion 和 长链推送 saveVersion 不同步的问题,在这里手动更新
|
||||
// In order to solve the problem that the canvas interface gets saveVersion and the long-chain push saveVersion are not synchronized, manually update here
|
||||
this.dependencyEntity.addSaveVersion();
|
||||
}
|
||||
};
|
||||
@@ -173,7 +173,7 @@ export class WorkflowOperationService {
|
||||
...this.mocksetFgOption,
|
||||
};
|
||||
|
||||
// 1. 查看历史试运行时,需要传入commitId. 2.协作模式下非草稿态时试运行传入commitId防止回退为草稿
|
||||
// 1. When the practice runs to view the history, you need to pass in the commitId. 2. When the practice runs in non-draft mode in cooperation mode, pass in the commitId to prevent the fallback to draft
|
||||
const commitId =
|
||||
this.globalState.isViewHistory ||
|
||||
(this.globalState.isCollaboratorMode &&
|
||||
@@ -211,7 +211,7 @@ export class WorkflowOperationService {
|
||||
params.log_id = this.logId;
|
||||
}
|
||||
|
||||
// 如果是子流程的日志,暂时不走异步查询,后端有 bug
|
||||
// If it is the log of the subprocess, the asynchronous query will not be done for the time being, and there is a bug in the backend.
|
||||
params.need_async = !subExecuteId;
|
||||
|
||||
const executeResult = await workflowApi.GetWorkFlowProcess(params);
|
||||
|
||||
@@ -49,17 +49,17 @@ import { TestRunReporterService } from './test-run-reporter-service';
|
||||
const LOOP_GAP_TIME = 300;
|
||||
|
||||
export enum TestRunState {
|
||||
/** 空置状态 */
|
||||
/** vacant state */
|
||||
Idle = 'idle',
|
||||
/** 执行中 */
|
||||
/** in progress */
|
||||
Executing = 'executing',
|
||||
/** 取消 */
|
||||
/** cancel */
|
||||
Canceled = 'canceled',
|
||||
/** 暂停 */
|
||||
/** pause */
|
||||
Paused = 'paused',
|
||||
/** 成功 */
|
||||
/** success */
|
||||
Succeed = 'succeed',
|
||||
// 失败
|
||||
// fail
|
||||
Failed = 'failed',
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ const ExecuteStatusToTestRunStateMap = {
|
||||
};
|
||||
|
||||
export interface TestRunResultInfo {
|
||||
// 执行id
|
||||
// execution id
|
||||
executeId?: string;
|
||||
}
|
||||
|
||||
@@ -80,12 +80,12 @@ interface TestRunOneNodeOptions {
|
||||
batch?: Record<string, string>;
|
||||
setting?: Record<string, string>;
|
||||
botId?: string;
|
||||
/** 是否选择应用 */
|
||||
/** Whether to choose the application */
|
||||
useProject?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workflow 执行
|
||||
* Workflow execution
|
||||
*/
|
||||
@injectable()
|
||||
export class WorkflowRunService {
|
||||
@@ -131,23 +131,23 @@ export class WorkflowRunService {
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
/**
|
||||
* 画布销毁的时候触发
|
||||
* Triggered when the canvas is destroyed
|
||||
*/
|
||||
this.playground.toDispose.onDispose(() => this.dispose());
|
||||
|
||||
this.onTestRunStateChange(({ prevState, curState }) => {
|
||||
// 监听state变化, 对testrun结果进行上报
|
||||
// Monitor state changes and report testrun results
|
||||
this.reportTestRunResult(prevState, curState);
|
||||
});
|
||||
}
|
||||
|
||||
dispose() {
|
||||
/** 画布销毁,清除所有 testForm 缓存数据 */
|
||||
/** Canvas destroyed, clearing all testForm cached data */
|
||||
this.testFormState.clearFormData();
|
||||
this.testFormState.clearTestFormDefaultValue();
|
||||
/** 销毁时解冻 test run */
|
||||
/** Thaw test run on destruction */
|
||||
this.testFormState.unfreezeTestRun();
|
||||
// 清空运行状态
|
||||
// Clear dry running state
|
||||
this.clearTestRun();
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ export class WorkflowRunService {
|
||||
clearTestRunResult = () => {
|
||||
this.testFormState.unfreezeTestRun();
|
||||
this.globalState.viewStatus = WorkflowExecStatus.DEFAULT;
|
||||
// 清空节点结果,避免 test run 的时候回显
|
||||
// Clear the node results to avoid echo when the test runs
|
||||
if (this.execState.hasNodeResult) {
|
||||
this.execState.clearNodeResult();
|
||||
}
|
||||
@@ -174,7 +174,7 @@ export class WorkflowRunService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 清空运行状态
|
||||
* Clear dry running state
|
||||
*/
|
||||
clearTestRunState = () => {
|
||||
this.setTestRunState(TestRunState.Idle);
|
||||
@@ -198,7 +198,7 @@ export class WorkflowRunService {
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
// 无论是否取消成功,中止状态下取消,需要恢复轮训
|
||||
// Whether the cancellation is successful or not, if it is cancelled in the suspended state, the rotation needs to be resumed.
|
||||
this.continueTestRun();
|
||||
}
|
||||
};
|
||||
@@ -211,13 +211,13 @@ export class WorkflowRunService {
|
||||
projectId,
|
||||
nodeEvents,
|
||||
}: GetWorkFlowProcessData): void => {
|
||||
// 更新各个节点状态
|
||||
// Update the status of each node
|
||||
if (nodeResults && nodeResults.length) {
|
||||
nodeResults.forEach((nodeResult: NodeResult) => {
|
||||
const { nodeId } = nodeResult;
|
||||
if (nodeId) {
|
||||
this.execState.setNodeExecResult(nodeId, nodeResult);
|
||||
// 更新节点的线条状态
|
||||
// Update the line state of a node
|
||||
const currentLines = this.linesManager
|
||||
.getAllLines()
|
||||
.filter(line => line?.to?.id === nodeResult.nodeId);
|
||||
@@ -234,7 +234,7 @@ export class WorkflowRunService {
|
||||
);
|
||||
});
|
||||
|
||||
// 更新节点错误
|
||||
// update node error
|
||||
const errorLevel = nodeResult.errorLevel?.toLocaleLowerCase() || '';
|
||||
if (['error', 'warning', 'pending'].includes(errorLevel || '')) {
|
||||
this.execState.setNodeError(nodeId, [
|
||||
@@ -255,7 +255,7 @@ export class WorkflowRunService {
|
||||
this.execState.updateConfig({
|
||||
projectId,
|
||||
executeLogId: executeId,
|
||||
// 仅当运行结果为 cancel 或者 fail 时 reason 字段才有效
|
||||
// The reason field is only valid if the run result is cancel or fail
|
||||
systemError:
|
||||
executeStatus &&
|
||||
[WorkflowExeStatus.Cancel, WorkflowExeStatus.Fail].includes(
|
||||
@@ -267,8 +267,8 @@ export class WorkflowRunService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取执行结果, 以及对服务返回数据进行预处理.
|
||||
* 可支持用执行 ID 获取, 或者直接传入服务返回数据
|
||||
* Obtain execution results and preprocess the data returned by the service.
|
||||
* Can support fetching with execution ID, or directly passing data back to the service
|
||||
*/
|
||||
runProcess = async ({
|
||||
executeId,
|
||||
@@ -283,7 +283,7 @@ export class WorkflowRunService {
|
||||
? processResp
|
||||
: (await this.operationService.getProcess(executeId, subExecuteId)).data;
|
||||
|
||||
// 一个远古的 bug ,后端返回 Warn ,前端消费 warning 。改代码影响面太大,因此在这里做一下转换
|
||||
// An ancient bug, the backend returns Warn, and the front-end consumes Warning. Changing the code has too much impact, so do the conversion here.
|
||||
data?.nodeResults?.forEach(node => {
|
||||
if (node.errorLevel === 'Warn') {
|
||||
node.errorLevel = 'warning';
|
||||
@@ -306,12 +306,12 @@ export class WorkflowRunService {
|
||||
return data || {};
|
||||
};
|
||||
|
||||
// 暂停test run
|
||||
// Pause test run
|
||||
pauseTestRun = () => {
|
||||
this.setTestRunState(TestRunState.Paused);
|
||||
};
|
||||
|
||||
// 继续test run
|
||||
// Continue the test run
|
||||
continueTestRun = () => {
|
||||
if (this.testRunState === TestRunState.Paused) {
|
||||
this.setTestRunState(TestRunState.Executing);
|
||||
@@ -331,7 +331,7 @@ export class WorkflowRunService {
|
||||
});
|
||||
};
|
||||
|
||||
// copy 原本的逻辑,每过 300ms 进行一次轮询
|
||||
// Copy the original logic and poll every 300ms
|
||||
loop = async (executeId?: string) => {
|
||||
const result = await this.runProcess({ executeId });
|
||||
this.execState.updateConfig(result || {});
|
||||
@@ -350,16 +350,16 @@ export class WorkflowRunService {
|
||||
this.testFormState.unfreezeTestRun();
|
||||
this.globalState.viewStatus = WorkflowExecStatus.DONE;
|
||||
if (!this.globalState.isViewHistory) {
|
||||
// 根据试运行结果,刷新可发布状态
|
||||
// Refresh the publishable state based on practice run results
|
||||
this.globalState.reload();
|
||||
}
|
||||
};
|
||||
|
||||
/* 上报test run运行结果, 用于在商店中统计运行成功率 */
|
||||
/* Report the test run results to count the success rate in the store */
|
||||
reportTestRunResult = (prevState: TestRunState, curState: TestRunState) => {
|
||||
const { executeId, isSingleMode } = this.execState.config;
|
||||
|
||||
// 单节点模式不需要统计
|
||||
// Single node mode does not require statistics
|
||||
if (isSingleMode) {
|
||||
return;
|
||||
}
|
||||
@@ -367,7 +367,7 @@ export class WorkflowRunService {
|
||||
if (![TestRunState.Succeed, TestRunState.Failed].includes(curState)) {
|
||||
return;
|
||||
}
|
||||
/* 成功 */
|
||||
/* success */
|
||||
if (curState === TestRunState.Succeed) {
|
||||
sendTeaEvent(EVENT_NAMES.workflow_testrun_result_front, {
|
||||
space_id: this.globalState.spaceId,
|
||||
@@ -379,7 +379,7 @@ export class WorkflowRunService {
|
||||
}
|
||||
|
||||
if (curState === TestRunState.Failed) {
|
||||
/* 触发失败 */
|
||||
/* Trigger failed */
|
||||
if (prevState === TestRunState.Idle) {
|
||||
sendTeaEvent(EVENT_NAMES.workflow_testrun_result_front, {
|
||||
space_id: this.globalState.spaceId,
|
||||
@@ -390,7 +390,7 @@ export class WorkflowRunService {
|
||||
errtype: 'trigger_error',
|
||||
});
|
||||
}
|
||||
/* 运行失败 */
|
||||
/* Failed to run */
|
||||
sendTeaEvent(EVENT_NAMES.workflow_testrun_result_front, {
|
||||
space_id: this.globalState.spaceId,
|
||||
workflow_id: this.globalState.workflowId,
|
||||
@@ -404,12 +404,12 @@ export class WorkflowRunService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 运行 test run
|
||||
* Run test run
|
||||
*/
|
||||
testRun = async (
|
||||
input?: Record<string, string>,
|
||||
botId?: string,
|
||||
/** 当前选择的是否为应用 */
|
||||
/** Is the current selection an application? */
|
||||
useProject?: boolean,
|
||||
) => {
|
||||
if (this.globalState.config.saving) {
|
||||
@@ -422,7 +422,7 @@ export class WorkflowRunService {
|
||||
|
||||
try {
|
||||
this.execState.closeSideSheet();
|
||||
// 更新视图为运行中
|
||||
// Update view to running
|
||||
this.globalState.viewStatus = WorkflowExecStatus.EXECUTING;
|
||||
const baseParam: {
|
||||
workflow_id: string;
|
||||
@@ -433,12 +433,12 @@ export class WorkflowRunService {
|
||||
workflow_id: this.globalState.workflowId,
|
||||
space_id: this.globalState.spaceId,
|
||||
};
|
||||
/** 存在 variable 节点或者存在 variable 节点子流程的画布才需要传 bot_id,与 input 同级*/
|
||||
/** There is a variable node or a canvas with a variable node subprocess that needs to be passed bot_id, the same level as input*/
|
||||
if (botId) {
|
||||
const botIdKey = useProject ? 'project_id' : 'bot_id';
|
||||
baseParam[botIdKey] = botId;
|
||||
}
|
||||
// 如果是在 project 内,则 projectId 必传
|
||||
// If it is within the project, the projectId must be passed
|
||||
if (this.globalState.projectId && !baseParam.project_id) {
|
||||
baseParam.project_id = this.globalState.projectId;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ export class WorkflowRunService {
|
||||
});
|
||||
|
||||
executeId = result?.execute_id || '';
|
||||
// 有执行 id,test run 运行成功
|
||||
// There is an execution id, the test ran successfully
|
||||
if (executeId) {
|
||||
this.execState.updateConfig({
|
||||
executeId,
|
||||
@@ -485,28 +485,28 @@ export class WorkflowRunService {
|
||||
testrun_result: 'error',
|
||||
});
|
||||
} finally {
|
||||
// 运行失败打开弹窗
|
||||
// Failed to open pop-up window
|
||||
if (executeStatus === WorkflowExeStatus.Fail) {
|
||||
this.execState.openSideSheet();
|
||||
}
|
||||
|
||||
// 运行后,不管成功,还原 inPluginUpdated 值,避免一直 testrun
|
||||
// After running, regardless of success, restore the inPluginUpdated value to avoid testrun all the time.
|
||||
this.globalState.inPluginUpdated = false;
|
||||
this.setTestRunState(ExecuteStatusToTestRunStateMap[executeStatus]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取执行历史数据
|
||||
* Get execution history data
|
||||
*/
|
||||
getProcessResult = async (config: {
|
||||
/** 是否展示节点结果 */
|
||||
/** Whether to display node results */
|
||||
showNodeResults?: boolean;
|
||||
/** 指定执行 ID, 若不填, 则展示最近一次运行结果 */
|
||||
/** Specify the execution ID, if not, the last run result will be displayed */
|
||||
executeId?: string;
|
||||
/** 直接结果服务端返回 */
|
||||
/** Direct result server level return */
|
||||
processResp?: GetWorkFlowProcessData;
|
||||
/** 子流程执行id */
|
||||
/** subprocess execution id */
|
||||
subExecuteId?: string;
|
||||
}) => {
|
||||
const { showNodeResults, executeId, processResp, subExecuteId } = config;
|
||||
@@ -522,9 +522,9 @@ export class WorkflowRunService {
|
||||
|
||||
if (showNodeResults) {
|
||||
/**
|
||||
* 只把结果数据同步到节点上,但是不改变 global.config.info.status
|
||||
* 否则上一次 test run 的结果会影响到现在流程是否能够发布的状态
|
||||
* 该状态只能由真正的 test run、后端数据等真实动作修改
|
||||
* Only synchronizes the resulting data to the node, but does not change global.config.info. Status
|
||||
* Otherwise, the result of the last test run will affect whether the current process can be released
|
||||
* This state can only be modified by real actions such as real test runs, back-end data, etc
|
||||
*/
|
||||
this.globalState.viewStatus = WorkflowExecStatus.DONE;
|
||||
this.updateExecuteState(omit(result, 'nodeEvents'));
|
||||
@@ -545,7 +545,7 @@ export class WorkflowRunService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 test form schema 对应的 node
|
||||
* Get the node corresponding to the current test form schema
|
||||
*/
|
||||
getTestFormNode() {
|
||||
const schema = this.testFormState.formSchema;
|
||||
@@ -556,7 +556,7 @@ export class WorkflowRunService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 单节点运行
|
||||
* single node operation
|
||||
*/
|
||||
async testRunOneNode(options: TestRunOneNodeOptions) {
|
||||
const { nodeId, input, batch, setting, botId, useProject } = options;
|
||||
@@ -583,7 +583,7 @@ export class WorkflowRunService {
|
||||
}
|
||||
}
|
||||
|
||||
// 在项目内的话,默认使用 project_id
|
||||
// Within the project, project_id is used by default
|
||||
if (this.globalState.projectId) {
|
||||
Object.assign(botIdParams, { project_id: this.globalState.projectId });
|
||||
}
|
||||
@@ -628,7 +628,7 @@ export class WorkflowRunService {
|
||||
this.testFormState.setTestFormDefaultValue(defaultValue);
|
||||
};
|
||||
|
||||
/** 轮询获取实时的数据 */
|
||||
/** Polling for real-time data */
|
||||
async getRTProcessResult(obj: { executeId?: string }) {
|
||||
const { executeId } = obj;
|
||||
if (!executeId) {
|
||||
@@ -637,29 +637,29 @@ export class WorkflowRunService {
|
||||
let executeStatus;
|
||||
|
||||
try {
|
||||
/** 直接请求一次数据 */
|
||||
/** Request data directly */
|
||||
const result = await this.runProcess({ executeId });
|
||||
/** 更新数据到视图 */
|
||||
/** Update data to view */
|
||||
this.execState.updateConfig(result || {});
|
||||
this.updateExecuteState(result);
|
||||
executeStatus = result?.executeStatus;
|
||||
/**
|
||||
* 当仍然处于运行中,则开启轮询
|
||||
* chatflow 场景,后端可能返回 0,这时候也需要执行轮询
|
||||
* When still running, turn on polling
|
||||
* Chatflow scenario, the backend may return 0, and polling is also required at this time
|
||||
*/
|
||||
if (
|
||||
result?.executeStatus === WorkflowExeStatus.Running ||
|
||||
(result?.executeStatus as number) === 0
|
||||
) {
|
||||
/** 开启轮询,需要先讲视图变为只读态 */
|
||||
/** To turn on polling, you need to first make the view read-only */
|
||||
this.globalState.viewStatus = WorkflowExecStatus.EXECUTING;
|
||||
this.setTestRunState(TestRunState.Executing);
|
||||
/**
|
||||
* 1. 为保证请求的节奏同步,这里也会 sleep
|
||||
* 2. 暂停同样对其有效,不过暂时没有这种业务场景
|
||||
* 1. To ensure the rhythm of the request is synchronized, sleep will also be done here
|
||||
* 2. The suspension is also valid for it, but there is no such business scenario for the time being
|
||||
*/
|
||||
await Promise.all([sleep(LOOP_GAP_TIME), this.waitContinue()]);
|
||||
/** 轮询 */
|
||||
/** poll */
|
||||
executeStatus = await this.loop(executeId);
|
||||
}
|
||||
this.finishProcess();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { debounce, isEmpty } from 'lodash-es';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { StackingContextManager } from '@flowgram-adapter/free-layout-editor';
|
||||
@@ -61,7 +61,7 @@ import {
|
||||
} from '../entities';
|
||||
import { WorkflowOperationService } from './workflow-operation-service';
|
||||
|
||||
// 这个非写死,不要用来判断开始节点,请用 flowNodeType
|
||||
// This is not written dead, do not use it to judge the start node, please use flowNodeType
|
||||
const START_NODE_ID = '100001';
|
||||
const END_NODE_ID = '900001';
|
||||
const CHAT_NODE_DEFAULT_ID = '110100';
|
||||
@@ -73,7 +73,7 @@ const RENDER_DELAY_TIME = 100;
|
||||
const ERROR_CODE_SAVE_VERSION_CONFLICT = '720702239';
|
||||
|
||||
/**
|
||||
* 创建默认,只有 start 和 end 节点
|
||||
* Create default, only start and end nodes
|
||||
*/
|
||||
function createDefaultJSON(flowMode: WorkflowMode): WorkflowJSON {
|
||||
if (flowMode === WorkflowMode.SceneFlow) {
|
||||
@@ -173,13 +173,13 @@ export class WorkflowSaveService {
|
||||
|
||||
protected saveOnChangeDisposable?: Disposable;
|
||||
|
||||
// 是否需要流转 test run 状态。当修改节点位置时,不需要重新 test run
|
||||
// Whether the test run state needs to be streamed. When changing the node location, there is no need to re-test run
|
||||
ignoreStatusTransfer = true;
|
||||
|
||||
/**
|
||||
* 获取 workflow schema json
|
||||
* @param commitId 流程的版本信息
|
||||
* @param type 流程版本的类型信息 提交或发布
|
||||
* Get workflow schema json
|
||||
* @Param commitId process version information
|
||||
* @Param type type information for process version, commit or publish
|
||||
*/
|
||||
loadWorkflowJson = async (
|
||||
commitId?: string,
|
||||
@@ -203,7 +203,7 @@ export class WorkflowSaveService {
|
||||
const isPreviewInProject = Boolean(projectId && projectCommitVersion);
|
||||
const hasExecuteId = Boolean(playgroundProps?.executeId);
|
||||
|
||||
// 如果是 project 查看历史版本
|
||||
// If it is a project, check the historical version.
|
||||
if (isPreviewInProject) {
|
||||
workflowJson = await this.globalState.loadHistory({
|
||||
commit_id: commitId as string,
|
||||
@@ -232,8 +232,8 @@ export class WorkflowSaveService {
|
||||
});
|
||||
} else if (playgroundProps?.from === 'communityTrial') {
|
||||
/**
|
||||
* 如果来自 community trial 无论是否有 commitId 都要取历史的版本
|
||||
* 主要应对在 trial 中 db 没有 commitId 请求最新 schema 的场景。数据清洗完毕后可删除该逻辑
|
||||
* If it comes from a community trial, the historical version must be taken regardless of whether there is a commitId or not.
|
||||
* Mainly deal with scenarios where db does not commitId request the latest schema in trial. This logic can be deleted after data cleaning is completed
|
||||
*/
|
||||
workflowJson = await this.globalState.loadHistory({
|
||||
commit_id: workflowCommitId,
|
||||
@@ -243,7 +243,7 @@ export class WorkflowSaveService {
|
||||
});
|
||||
} else {
|
||||
workflowJson = await this.globalState.load(workflowId, spaceId);
|
||||
// 流程初始化设置 saveVersion
|
||||
// Process initialization settings saveVersion
|
||||
const workflowInfo = this.globalState.config?.info;
|
||||
FLAGS?.['bot.automation.project_multi_tab'] &&
|
||||
projectId &&
|
||||
@@ -264,8 +264,8 @@ export class WorkflowSaveService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 对所有节点表单渲染前进行初始化,初始化完毕才会进行表单创建工作
|
||||
* @param nodes 所有节点数据
|
||||
* Initialize all node forms before rendering, and the form creation will not proceed until the initialization is completed.
|
||||
* @param nodes All node data
|
||||
*/
|
||||
async initNodeData(nodes: WorkflowNodeJSON[]) {
|
||||
const promises: Promise<void>[] = [];
|
||||
@@ -287,7 +287,7 @@ export class WorkflowSaveService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载文档数据
|
||||
* Load document data
|
||||
*/
|
||||
async loadDocument(doc: WorkflowDocument): Promise<void> {
|
||||
this.workflowDocument = doc;
|
||||
@@ -307,7 +307,7 @@ export class WorkflowSaveService {
|
||||
const userInfo = userStoreService.getUserInfo();
|
||||
const locale = userInfo?.locale ?? navigator.language ?? 'en-US';
|
||||
|
||||
// 加载节点信息
|
||||
// load node information
|
||||
const [, workflowJSON] = await Promise.all([
|
||||
this.context.loadNodeInfos(locale),
|
||||
this.loadWorkflowJson(),
|
||||
@@ -324,10 +324,10 @@ export class WorkflowSaveService {
|
||||
logger.error(e.message);
|
||||
}
|
||||
|
||||
// 加载大模型上下文
|
||||
// Load large model context
|
||||
this.context.models = this.modelsService.getModels() as Model[];
|
||||
|
||||
// 同步加载的 nodes 和 edges 到 workflow store
|
||||
// Synchronize loaded nodes and edges to workflow store
|
||||
useWorkflowStore.getState().setNodes(workflowJSON.nodes);
|
||||
useWorkflowStore.getState().setEdges(workflowJSON.edges);
|
||||
|
||||
@@ -335,7 +335,7 @@ export class WorkflowSaveService {
|
||||
|
||||
const renderStartTime = Date.now();
|
||||
|
||||
// 前置数据加载
|
||||
// preload
|
||||
await this.initNodeData(workflowJSON.nodes as WorkflowNodeJSON[]);
|
||||
|
||||
await this.workflowDocument.fromJSON(workflowJSON);
|
||||
@@ -345,7 +345,7 @@ export class WorkflowSaveService {
|
||||
loading: false,
|
||||
});
|
||||
projectApi?.setWidgetUIState('normal');
|
||||
// 有权限才能自动保存
|
||||
// Only with permission can it be automatically saved.
|
||||
if (!this.globalState.readonly) {
|
||||
this.saveOnChangeDisposable = doc.onContentChange(
|
||||
this.listenContentChange,
|
||||
@@ -406,26 +406,26 @@ export class WorkflowSaveService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认将开始节点居中展示
|
||||
* By default, the start node will be centered
|
||||
*/
|
||||
async fitView(): Promise<void> {
|
||||
// 等待节点渲染与布局计算
|
||||
// Waiting for node rendering and layout calculation
|
||||
await delay(RENDER_DELAY_TIME);
|
||||
|
||||
// 等待 DOM resize 更新
|
||||
// Wait for DOM resize update
|
||||
await new Promise<void>(resolve => {
|
||||
window.requestAnimationFrame(() => resolve());
|
||||
});
|
||||
|
||||
// 执行布局
|
||||
// execution layout
|
||||
this.workflowDocument.fitView(false);
|
||||
|
||||
// 等待布局后节点渲染
|
||||
// Wait for the node to render after layout
|
||||
await delay(RENDER_DELAY_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文档数据
|
||||
* Save document data
|
||||
*/
|
||||
save = async () => {
|
||||
const { getProjectApi } = this.globalState;
|
||||
@@ -433,7 +433,7 @@ export class WorkflowSaveService {
|
||||
const FLAGS = getFlags();
|
||||
|
||||
try {
|
||||
// 只读态禁用保存,如果在加载状态中,也禁止保存
|
||||
// Disable saving in read-only state, and also disable saving if in the loaded state
|
||||
if (this.globalState.readonly || this.globalState.loading) {
|
||||
return;
|
||||
}
|
||||
@@ -450,15 +450,15 @@ export class WorkflowSaveService {
|
||||
const json = await this.workflowDocument.toJSON();
|
||||
|
||||
if (this.globalState.config.schemaGray) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 临时字段
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- temporary field
|
||||
(json as any).versions = this.globalState.config.schemaGray;
|
||||
}
|
||||
|
||||
// 保存草稿,存储 workflow 的 nodes 和 edges 到 zustand store
|
||||
// Save the draft, store the nodes and edges of the workflow to zustand store
|
||||
useWorkflowStore.getState().setNodes(json.nodes);
|
||||
useWorkflowStore.getState().setEdges(json.edges);
|
||||
|
||||
// FIXME 这个问题还没定位清除,先阻止保存
|
||||
// The problem of FIXME has not been located and cleared, so prevent the saving first.
|
||||
if (json.nodes.length === 0) {
|
||||
projectApi?.setWidgetUIState('error');
|
||||
throw new CustomError(REPORT_EVENTS.parmasValidation, 'Saving Error');
|
||||
@@ -475,7 +475,7 @@ export class WorkflowSaveService {
|
||||
savingError: false,
|
||||
});
|
||||
projectApi?.setWidgetUIState('normal');
|
||||
// save 成功后获取最新的 saveVersion
|
||||
// Get the latest saveVersion after successful saving
|
||||
const workflowInfo = this.globalState.config.info;
|
||||
FLAGS?.['bot.automation.project_multi_tab'] &&
|
||||
this.globalState.projectId &&
|
||||
@@ -490,7 +490,7 @@ export class WorkflowSaveService {
|
||||
});
|
||||
projectApi?.setWidgetUIState('error');
|
||||
|
||||
// 新版本节点后续统一使用 e.name 是否为 CustomNodeError 来判断
|
||||
// The new version of the node will use e.name whether it is CustomNodeError to judge
|
||||
if (
|
||||
e.eventName === 'WorkflowSubWorkflowResourceLose' ||
|
||||
e.eventName === 'WorkflowApiNodeResourceLose' ||
|
||||
@@ -501,7 +501,7 @@ export class WorkflowSaveService {
|
||||
e.code === ERROR_CODE_SAVE_VERSION_CONFLICT &&
|
||||
FLAGS?.['bot.automation.project_multi_tab']
|
||||
) {
|
||||
// 保存时发现工作流版本冲突,提示用户刷新页面
|
||||
// A workflow version conflict is found when saving, prompting the user to refresh the page
|
||||
this.dependencyEntity.setRefreshModalVisible(true);
|
||||
throw e;
|
||||
} else {
|
||||
@@ -513,8 +513,8 @@ export class WorkflowSaveService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否为游离节点的改动
|
||||
* 游离节点修改无需重新 test run
|
||||
* Determine whether it is a change from a free node
|
||||
* Free node modification without re-test run
|
||||
*/
|
||||
isAssociateChange(entity: FlowNodeEntity | WorkflowLineEntity) {
|
||||
let isAssociateChange = false;
|
||||
@@ -555,7 +555,7 @@ export class WorkflowSaveService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 高优先级保存,包含节点内容、节点增删、线条增删
|
||||
* High priority save, including node content, node addition and deletion, line addition and deletion
|
||||
*/
|
||||
public highPrioritySave = debounce(() => {
|
||||
reporter.event({
|
||||
@@ -565,7 +565,7 @@ export class WorkflowSaveService {
|
||||
}, HIGH_DEBOUNCE_TIME);
|
||||
|
||||
/**
|
||||
* 低优先级保存,包含节点位置移动
|
||||
* Low-priority saving, including node location moves
|
||||
* @protected
|
||||
*/
|
||||
public lowPrioritySave = debounce(() => {
|
||||
@@ -585,7 +585,7 @@ export class WorkflowSaveService {
|
||||
};
|
||||
|
||||
/**
|
||||
* 重载文档数据
|
||||
* Overloading document data
|
||||
*/
|
||||
reloadDocument = async ({
|
||||
commitId,
|
||||
@@ -598,7 +598,7 @@ export class WorkflowSaveService {
|
||||
env?: string;
|
||||
customWorkflowJson?: WorkflowJSON;
|
||||
} = {}) => {
|
||||
// 等待 save 结束
|
||||
// Wait for the save to end
|
||||
|
||||
await this.waitSaving();
|
||||
|
||||
@@ -612,7 +612,7 @@ export class WorkflowSaveService {
|
||||
|
||||
this.saveOnChangeDisposable?.dispose();
|
||||
|
||||
// 前置数据加载
|
||||
// preload
|
||||
await this.initNodeData((workflowJson?.nodes as WorkflowNodeJSON[]) ?? []);
|
||||
await this.workflowDocument.reload(workflowJson, RELOAD_DELAY_TIME);
|
||||
if (!this.globalState.readonly) {
|
||||
|
||||
@@ -111,7 +111,7 @@ const formatSchemaError2WorkflowError = (data?: ValidateTreeInfo[]) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Workflow 执行状态校验服务
|
||||
* Workflow Execution Status Validation Service
|
||||
*/
|
||||
@injectable()
|
||||
export class WorkflowValidationService implements ValidationService {
|
||||
@@ -123,15 +123,15 @@ export class WorkflowValidationService implements ValidationService {
|
||||
|
||||
store = createStore();
|
||||
|
||||
/** 已校验节点 */
|
||||
/** Verified node */
|
||||
public validatedNodeMap: Record<string, boolean> = {};
|
||||
|
||||
/** 清除已校验节点状态 */
|
||||
/** Clear Verified Node State */
|
||||
public clearValidatedNodeMap() {
|
||||
this.validatedNodeMap = {};
|
||||
}
|
||||
|
||||
/** 校验节点 */
|
||||
/** check node */
|
||||
public async validateNode(node: WorkflowNodeEntity): Promise<ValidateResult> {
|
||||
const nodeErrorResult = this.validateNodeError(node);
|
||||
const formValidateResult = await this.validateForm(node);
|
||||
@@ -148,7 +148,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
return this.mergeValidateResult(...validateResults);
|
||||
}
|
||||
|
||||
/** 校验工作流 */
|
||||
/** validation workflow */
|
||||
public async validateWorkflow(): Promise<ValidateResult> {
|
||||
const nodes = this.document.getAssociatedNodes();
|
||||
const results: ValidateResult[] = await Promise.all(
|
||||
@@ -157,7 +157,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
return this.mergeValidateResult(...results);
|
||||
}
|
||||
|
||||
/** 合并校验结果 */
|
||||
/** merge validation result */
|
||||
private mergeValidateResult(...result: ValidateResult[]): ValidateResult {
|
||||
const hasError = result.some(item => item.hasError);
|
||||
|
||||
@@ -183,7 +183,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
};
|
||||
}
|
||||
|
||||
/** 校验节点错误 */
|
||||
/** check node error */
|
||||
private validateNodeError(
|
||||
node: WorkflowNodeEntity,
|
||||
): ValidateResult | undefined {
|
||||
@@ -206,7 +206,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
};
|
||||
}
|
||||
|
||||
/** 校验节点表单 */
|
||||
/** Verify Node Form */
|
||||
private async validateForm(
|
||||
node: WorkflowNodeEntity,
|
||||
): Promise<ValidateResult | undefined> {
|
||||
@@ -217,7 +217,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
return;
|
||||
}
|
||||
|
||||
// 节点表单校验
|
||||
// Node Form Validation
|
||||
const feedbacks = await formData.formModel.validateWithFeedbacks();
|
||||
const nodeFormError = feedbacks
|
||||
.filter(
|
||||
@@ -227,7 +227,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
)
|
||||
.map(feedback => {
|
||||
let feedbackText = feedback.feedbackText || '';
|
||||
// output的feedbacks需要解析, 暂时没有好的办法判断不同的feedbacks
|
||||
// The output feedbacks need to be parsed, and there is no good way to judge different feedbacks for the time being.
|
||||
try {
|
||||
const parsedError = JSON.parse(feedbackText);
|
||||
const { issues, name } = parsedError;
|
||||
@@ -258,7 +258,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
return formValidateResult;
|
||||
}
|
||||
|
||||
/** 校验子画布端口 */
|
||||
/** check subcanvas port */
|
||||
private validateSubCanvasPort(
|
||||
node: WorkflowNodeEntity,
|
||||
): ValidateResult | undefined {
|
||||
@@ -304,7 +304,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
} else {
|
||||
inputPort.hasError = false;
|
||||
}
|
||||
// 所有叶子结点都是结束节点
|
||||
// All leaf nodes are end nodes
|
||||
const isAllLeafEnds = canvasNode.collapsedChildren
|
||||
.filter(
|
||||
childNode =>
|
||||
@@ -340,7 +340,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验异常设置端口
|
||||
* check exception setting port
|
||||
*/
|
||||
private validateSettingOnErrorPort(
|
||||
node: WorkflowNodeEntity,
|
||||
@@ -388,7 +388,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
};
|
||||
}
|
||||
|
||||
/** 校验画布 schema */
|
||||
/** Validation canvas schema */
|
||||
public async validateSchema() {
|
||||
const json = await this.document.toJSON();
|
||||
const params =
|
||||
@@ -412,7 +412,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
};
|
||||
}
|
||||
|
||||
/** 新版校验画布 schema */
|
||||
/** New validation canvas schema */
|
||||
public async validateSchemaV2() {
|
||||
const params: ValidateTreeRequest = {
|
||||
workflow_id: this.globalState.workflowId,
|
||||
@@ -458,7 +458,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
}
|
||||
isLineError(fromId: string, toId?: string) {
|
||||
const errors = this.store.getState().errorsV2;
|
||||
/** 仅查找本 workflow 的线条错误 */
|
||||
/** Find only line errors for this workflow */
|
||||
const myErrors = errors[this.globalState.workflowId]?.errors;
|
||||
if (!myErrors) {
|
||||
return false;
|
||||
@@ -470,7 +470,7 @@ export class WorkflowValidationService implements ValidationService {
|
||||
return !!lineError;
|
||||
}
|
||||
|
||||
/** 非响应式,慎用 */
|
||||
/** Non-responsive, use with caution */
|
||||
get validating() {
|
||||
return this.store.getState().validating;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user