chore: replace all cn comments of fe to en version by volc api (#320)

This commit is contained in:
tecvan
2025-07-31 10:32:15 +08:00
committed by GitHub
parent 716ec0cba8
commit 71f6245a01
2960 changed files with 15545 additions and 15545 deletions

View File

@@ -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;

View File

@@ -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',

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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_v1apiName 不会变还是 getStockname 才是更新后的的 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,
});
}

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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: (

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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?.();
});

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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: {

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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 || '';
// 有执行 idtest 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();

View File

@@ -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) {

View File

@@ -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 || '';
// outputfeedbacks需要解析, 暂时没有好的办法判断不同的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;
}