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

@@ -21,7 +21,7 @@ export enum LLMModel {
YunqueModel = 1706077826,
}
/** 海外默认选择 GPT_4O国内默认选择豆包 Function Call 模型,专业版则默认选择第一个 */
/** GPT_4O is selected by default overseas, the bean bag Function Call model is selected by default in China, and the first one is selected by default in the professional version */
export const DEFAULT_MODEL_TYPE = IS_OVERSEA
? LLMModel.GPT_4O
: LLMModel.YunqueModel;
@@ -43,16 +43,16 @@ export const DEFAULT_BATCH_CONCURRENT_SIZE = BATCH_CONCURRENT_SIZE_MAX;
export const DEFAULT_BATCH_SIZE = 100;
export const INTENT_NODE_MODE = {
/** 意图识别节点极简模式 */
/** intent recognition node minimalist pattern */
MINIMAL: 'top_speed',
/** 意图识别完整模式 */
/** intent recognition full pattern */
STANDARD: 'all',
};
/** 极速版意图识别选项最大数目 */
/** Lite version maximum number of intent recognition options */
export const MINIMAL_INTENT_ITEMS = 10;
/** 标准版意图识别选项最大数目 */
/** Standard Edition maximum number of intent recognition options */
export const STANDARD_INTENT_ITEMS = 50;
export const SYSTEM_DELIMITER = {
@@ -97,16 +97,16 @@ export const DEFAULT_DELIMITER_OPTIONS = [
},
];
/** 场景工作流角色信息关键字 */
/** scenario workflow role information keyword */
export const roleInformationKeyword = 'role_information';
/** 节点默认宽高(带有输入/输出) */
/** Node default width and height (with input/output) */
export const DEFAULT_NODE_SIZE = {
width: 360,
height: 104.7,
};
/** 输入参数 label 样式 */
/** Input parameter label style */
export const DEFAULT_INPUT_LABEL_STYLE = {
width: '40%',
};

View File

@@ -24,36 +24,36 @@ import { type ReleasedWorkflow } from '@coze-arch/bot-api/workflow_api';
import { type ApiNodeDetailDTO } from '../../typings';
/**
* api 节点上存储的 api 的相关数据
* Data related to the API stored on the API node
*/
export type ApiNodeData = CommonNodeData &
Readonly<
Partial<ApiNodeDetailDTO> & {
/**
* 项目内插件节点需要保存 projectId
* The plug-in node in the project needs to save the projectId.
*/
projectId?: string;
/** 该插件的最新版本的时间戳 */
/** The latest version of the plugin timestamp */
latestVersionTs?: string;
/** 插件最新版本的展示名称,形如 v1.0.0 */
/** The display name of the latest version of the plugin, like v1.0.0 */
latestVersionName?: string;
/** 该插件当前版本的展示名称,形如 v1.0.0 */
/** The display name of the current version of the plugin, in the form of v1.0.0 */
versionName?: string;
}
>;
/**
* 子流程节点上存储的相关数据
* Related data stored on the subprocess node
*/
export type SubWorkflowNodeData = CommonNodeData &
Readonly<Omit<ReleasedWorkflow, 'inputs' | 'outputs'>> & {
/** 子流程节点输入定义 */
/** Subprocess Node Input Definition */
inputsDefinition: DTODefine.InputVariableDTO[];
/**
* 项目内子流程需要保存 projectId
* The sub-process in the project needs to save the projectId.
*/
projectId?: string;
/** 该子流程的最新版本 */
/** The latest version of the subprocess */
latestVersion?: string;
};
@@ -64,25 +64,25 @@ export type QuestionNodeData = CommonNodeData & {
};
/**
* 通用节点类型的相关数据
* 基础节点定义见类型 BasicStandardNodeTypes
* Related data for common node types
* See Type BasicStandardNodeTypes for basic node definitions
*/
export interface CommonNodeData {
/**
*
* 节点图标
* Node icon
*/
readonly icon: string;
/**
* 节点描述
* node description
*/
description: string;
/**
* 节点标题
* Node title
*/
title: string;
/**
* 节点主色
* Node main color
*/
mainColor: string;
}

View File

@@ -15,12 +15,12 @@
*/
/**
* 这个模块是干什么的
* 在 workflow 的 node 模型中,默认对于数据的存储只有表单,即 formMeta。这部分数据实际上代表的是提交给后端用来做 workflow 运行的数据
* 然而实际业务场景中,我们需要的不仅是提交给后端用来做运行的数据,还有一些前端业务场景下需要消费,而后端用不到的数据。比如:
* 1. api 节点的 spaceId、发布状态
* 2. 子流程节点的 spaceId、发布状态
* 所以这个模块增加一个 NodeData 实体来管理每一个node 上的一些数据,让业务层消费使用
* What is this module for?
* In the node model of workflow, the default storage for data is only the form, that is, formMeta. This part of the data actually represents the data submitted to the backend for workflow execution
* However, in the actual business scenario, we need not only the data submitted to the back-end for operation, but also some data that needs to be consumed in the front-end business scenario, but not used by the back-end. For example:
* 1. spaceId and release status of the api node
* 2. SpaceId and publication status of the child process node
* So this module adds a NodeData entity to manage some data on each node for consumption and use by the business layer
*/
import { EntityData } from '@flowgram-adapter/free-layout-editor';
@@ -43,12 +43,12 @@ export class WorkflowNodeData extends EntityData {
/**
*
* @param data
* 设置节点上除form之外的数据
* 泛型必须传入节点类型 StandardNodeType
* Set up data other than form on the node
* Generics must pass in the node type StandardNodeType
*/
setNodeData<T extends keyof NodeData = never>(data: NodeData[T]) {
if (this.hasSetNodeData) {
// 撤销重做时会重复设置,没必要报错
// The settings will be repeated when undoing and redoing, there is no need to report an error.
console.warn(`node ${this.entity.id} has already set WorkflowNodeData`);
return;
}
@@ -60,8 +60,8 @@ export class WorkflowNodeData extends EntityData {
/**
*
* @param data
* 更新数据只放非readonly字段的更新
* 泛型必须传入节点类型 StandardNodeType
* Update data, put only non-readonly field updates
* Generics must pass in the node type StandardNodeType
*/
updateNodeData<T extends keyof NodeData = never>(
data: Partial<EditAbleNodeData<T>>,
@@ -71,7 +71,7 @@ export class WorkflowNodeData extends EntityData {
/**
*
* @returns
* 获取节点上除form之外的数据
* Get data other than form on the node
*/
getNodeData<T extends keyof NodeData>(): NodeData[T] {
return this.nodeData;

View File

@@ -30,12 +30,12 @@ export class WorkflowNodesService {
@inject(EntityManager) protected readonly entityManager: EntityManager;
private nanoid = customAlphabet('1234567890', 5);
/**
* 节点标题变化
* Node header change
*/
readonly onNodesTitleChange = this.onNodesTitleChangeEmitter.event;
/**
* 节点标题更新
* Node header update
* @param node
*/
getNodeTitle(node: WorkflowNodeEntity): string {
@@ -48,7 +48,7 @@ export class WorkflowNodesService {
}
/**
* 获取所有节点
* Get all nodes
*/
getAllNodes(ignoreNode?: WorkflowNodeEntity): WorkflowNodeEntity[] {
return this.entityManager
@@ -56,13 +56,13 @@ export class WorkflowNodesService {
.filter(n => n.id !== 'root' && n !== ignoreNode);
}
/**
* 获取所有节点的标题
* Get the titles of all nodes
*/
getAllTitles(ignoreNode?: WorkflowNodeEntity): string[] {
return this.getAllNodes(ignoreNode).map(node => this.getNodeTitle(node));
}
/**
* 获取开始节点
* Get start node
*/
getStartNode(): WorkflowNodeEntity {
return this.entityManager
@@ -70,14 +70,14 @@ export class WorkflowNodesService {
.find(node => node.isStart) as WorkflowNodeEntity;
}
/**
* 触发节点标题更新事件
* Trigger node header update event
*/
fireNodesTitleChange(): void {
this.onNodesTitleChangeEmitter.fire();
}
/**
* 创建不会重复的title
* Create non-duplicate titles
*
* abc_1 -> abc_2
*/
@@ -110,11 +110,11 @@ export class WorkflowNodesService {
return newTitle;
}
/** 创建唯一ID */
/** Create a unique ID */
createUniqID() {
let id: string;
do {
// 防止 id 以 0 开头,后端会转成 int64 导致 0 丢失,从而一些 id 匹配不上
// To prevent the id from starting with 0, the backend will be converted to int64, resulting in 0 loss, so some IDs cannot match
id = `1${this.nanoid()}`;
} while (this.entityManager.getEntityById(id));
return id;

View File

@@ -18,7 +18,7 @@
import { StandardNodeType } from '@coze-workflow/base';
/**
* 使用 V2 版本异常设置的节点
* Nodes using V2 version exception settings
*/
export const SETTING_ON_ERROR_V2_NODES = [
StandardNodeType.Code,
@@ -35,17 +35,17 @@ export const SETTING_ON_ERROR_V2_NODES = [
];
/**
* 使用V1的版本异常设置
* Version exception settings using V1
*/
export const SETTING_ON_ERROR_V1_NODES = [StandardNodeType.Http];
/**
* 有动态port的节点
* Nodes with dynamic ports
*/
export const SETTING_ON_ERROR_DYNAMIC_PORT_NODES = [StandardNodeType.Intent];
/**
* 开启异常的节点
* Open abnormal node
*/
export const SETTING_ON_ERROR_NODES = [
...SETTING_ON_ERROR_V1_NODES,
@@ -53,17 +53,17 @@ export const SETTING_ON_ERROR_NODES = [
];
/**
* 异常端口
* abnormal port
*/
export const SETTING_ON_ERROR_PORT = 'branch_error';
/**
* 超时最小100ms
* Timeout minimum 100ms;
*/
export const SETTING_ON_ERROR_MIN_TIMEOUT = 100;
/**
* 其他节点默认1分钟最大1分钟
* Other nodes: default 1 minute, maximum 1 minute;
*/
export const SETTING_ON_ERROR_DEFAULT_TIMEOUT = {
default: 60 * 1000,
@@ -71,9 +71,9 @@ export const SETTING_ON_ERROR_DEFAULT_TIMEOUT = {
};
/**
* 节点配置
* LLM默认3分钟最大10分钟
* 插件默认3分钟最大3分钟
* Node configuration
* LLM: Default 3 minutes, maximum 10 minutes;
* Plugin: Default 3 minutes, maximum 3 minutes;
*/
export const SETTING_ON_ERROR_NODES_CONFIG = {
[StandardNodeType.LLM]: {

View File

@@ -63,8 +63,8 @@ const settingOnErrorInitV2 = (
const timeoutConfig = getTimeoutConfig(context?.node);
if (!timeoutMs) {
// 如果没有设置超时时间,且有初始值配置,则设置初始值
// 如LLM后端默认是10min历史数据需要设置为init的10min新加的节点显示默认的default的3min
// If no timeout is set and there is an initial value configuration, set the initial value
// For example, the default of the LLM backend is 10min, the historical data needs to be set to 10min of init, and the newly added node displays the default default 3min.
if (value && timeoutConfig?.init) {
timeoutMs = timeoutConfig.init;
} else {

View File

@@ -19,7 +19,7 @@ import { useCurrentEntity } from '@flowgram-adapter/free-layout-editor';
import { getTimeoutConfig } from '../utils/get-timeout-config';
/**
* 获取超时配置
* Get timeout configuration
* @returns
*/
export const useTimeoutConfig = (): {

View File

@@ -17,10 +17,10 @@
import { type ViewVariableTreeNode } from '@coze-workflow/base';
/**
* 异常处理类型
* 1 直接中断
* 2 返回设定内容,
* 3 执行异常流程
* exception handling type
* 1 Direct interruption
* 2 Return to the setting content,
* 3 Execute abnormal flow
*/
export enum SettingOnErrorProcessType {
BREAK = 1,
@@ -29,11 +29,11 @@ export enum SettingOnErrorProcessType {
}
/**
* 异常处理额外数据
* Exception handling extra data
*/
export interface SettingOnErrorExt {
/**
* LLM节点重试的备选模型
* Alternative Model for LLM Node Retry
*/
backupLLmParam?: {
modelName?: string;
@@ -49,34 +49,34 @@ export interface SettingOnErrorExt {
interface SettingOnErrorBase {
/**
* 处理类型
* processing type
*/
processType?: SettingOnErrorProcessType;
/**
* 超时时间 毫秒
* Timeout, milliseconds
*/
timeoutMs?: number;
/**
* 重试次数 0 表示不重试
* Number of retries 0 means no retries
*/
retryTimes?: number;
}
/**
* 异常处理前端结构
* Exception handling front-end architecture
*/
export interface SettingOnErrorVO extends SettingOnErrorBase {
/**
* 是否开启异常处理
* Whether to enable exception handling
*/
settingOnErrorIsOpen?: boolean;
/**
* 发生异常处理的默认值
* Default value for exception handling to occur
*/
settingOnErrorJSON?: string;
/**
* 其他设置
* Other settings
*/
ext?: SettingOnErrorExt;
}
@@ -84,19 +84,19 @@ export interface SettingOnErrorVO extends SettingOnErrorBase {
export type SettingOnErrorValue = SettingOnErrorVO;
/**
* 异常处理后端结构
* exception handling backend structure
*/
export interface SettingOnErrorDTO extends SettingOnErrorBase {
/**
* 是否开启异常处理
* Whether to enable exception handling
*/
switch: boolean;
/**
* 发生异常处理的默认值
* Default value for exception handling to occur
*/
dataOnErr: string;
/**
* 其他设置
* Other settings
*/
ext?: {
backupLLmParam?: string;
@@ -104,7 +104,7 @@ export interface SettingOnErrorDTO extends SettingOnErrorBase {
}
/**
* 有异常设置的后端节点数据
* Backend node data with abnormal settings
*/
export interface NodeValueWithSettingOnErrorDTO {
inputs?: {
@@ -117,7 +117,7 @@ export interface NodeValueWithSettingOnErrorDTO {
}
/**
* 有异常设置的前端节点数据
* Front-end node data with exception settings
*/
export interface NodeValueWithSettingOnErrorVO {
settingOnError?: SettingOnErrorVO;

View File

@@ -23,7 +23,7 @@ import {
} from './constants';
/**
* 是不是v2版本的节点
* Is it a node of the v2 version?
* @param type
* @returns
*/
@@ -31,7 +31,7 @@ export const isSettingOnErrorV2 = (type?: StandardNodeType) =>
type && SETTING_ON_ERROR_V2_NODES.includes(type);
/**
* 是不是开启异常设置的节点
* Is it the node with the abnormal setting turned on?
* @param type
* @returns
*/
@@ -39,7 +39,7 @@ export const isSettingOnError = (type?: StandardNodeType) =>
type && SETTING_ON_ERROR_NODES.includes(type);
/**
* 是不是动态通道的节点
* Is it a node of the dynamic channel?
* @param type
* @returns
*/

View File

@@ -26,7 +26,7 @@ import {
import { WorkflowNodeData } from '../../entity-datas';
/**
* 是不是端插件
* Is it a side plug-in?
* @param node
* @returns
*/
@@ -45,7 +45,7 @@ const isLocalPlugin = (node?: WorkflowNodeEntity) => {
};
/**
* 获取节点超时配置
* Get node timeout configuration
*/
export const getTimeoutConfig = (
node?: WorkflowNodeEntity,

View File

@@ -31,7 +31,7 @@ const includeFn = isSettingOnErrorV2 => v =>
settingOnErrorNames(isSettingOnErrorV2).includes(v.name);
/**
* 向 output 中添加/剔除 errorBody
* Add/remove errorBody to output
*/
export const getOutputsWithErrorBody = ({
value,
@@ -47,9 +47,9 @@ export const getOutputsWithErrorBody = ({
if (!value) {
return value;
}
// 添加 errorBody
// Add errorBody
if (isOpen) {
// batch 模式下,在第一层的 children 里追加 errorBody
// In batch mode, append errorBody to children in the first layer
if (isBatch) {
return [
{
@@ -61,7 +61,7 @@ export const getOutputsWithErrorBody = ({
],
},
];
// single 模式下,在第一层追加 errorBody
// In single mode, append an errorBody to the first layer
} else {
return [
...(value ?? []).filter(excludeFn(isSettingOnErrorV2)),
@@ -69,9 +69,9 @@ export const getOutputsWithErrorBody = ({
...(isSettingOnErrorV2 ? [generateIsSuccessMeta()] : []),
];
}
// 剔除 errorBody
// errorBody
} else {
// batch 模式下,从第一层的 children 中剔除
// In batch mode, remove children from the first layer
if (isBatch) {
const [one, ...rest] = value;
return [
@@ -83,7 +83,7 @@ export const getOutputsWithErrorBody = ({
},
...rest,
];
// single 模式下,从第一层的 children 中剔除
// In single mode, remove children from the first layer
} else {
return [...(value ?? []).filter(excludeFn(isSettingOnErrorV2))];
}
@@ -91,7 +91,7 @@ export const getOutputsWithErrorBody = ({
};
/**
* output 属性排序,保证 errorBody 在最下面
* The output property is sorted to ensure that errorBody is at the bottom
*/
export const sortErrorBody = ({
value,
@@ -126,7 +126,7 @@ export const sortErrorBody = ({
};
/**
* 把 value 中的 errorBody 删除掉
* Remove the errorBody from the value
*/
export const getExcludeErrorBody = ({
value,

View File

@@ -38,7 +38,7 @@ export const toListRefSchema = (value: string[]): ListRefSchema => {
content: {
source: 'block-output',
blockID: `${nodeId}`,
name: keyPaths.join('.'), // 这是使用当前循环的变量,固定名字叫item
name: keyPaths.join('.'), // This is the variable that uses the current loop, with the fixed name item.
},
},
};

View File

@@ -57,7 +57,7 @@ export interface ApiNodeIdentifier {
export type DebugExample = OriginDebugExample;
/**
* Plugin扩展协议新增的属性
* Plugin extension protocol added properties
*
*/
export interface PluginExtendProps {
@@ -74,8 +74,8 @@ export interface PluginExtendProps {
}
/**
* 接口 /api/workflow_api/apiDetail 返回的插件数据结构
* 由于 inputs outputs 等参数类型后端没有定义清楚,这里补充完善下
* Plugin data structures returned by interface /api/workflow_api/apiDetail
* Since the backend of parameter types such as inputs and outputs is not clearly defined, it will be supplemented here.
*/
export type ApiNodeDetailDTO = Required<ApiDetailData> & {
inputs: (VariableMetaDTO & PluginExtendProps)[]; // name, type, schema, required, description
@@ -85,7 +85,7 @@ export type ApiNodeDetailDTO = Required<ApiDetailData> & {
};
/**
* 插件节点数据部分结构定义后端
* Plug-in node data part structure definition backend
*/
export interface ApiNodeDataDTO {
data: {

View File

@@ -34,14 +34,14 @@ export interface PlaygroundContext {
readonly variableValidationService: WorkflowVariableValidationService;
/**
* 根据meta 类型获取信息
* Get information by meta type
* @param type
*/
getNodeTemplateInfoByType: (
type: StandardNodeType,
) => NodeTemplateInfo | undefined;
/**
* 是否为 不可编辑模式
* Yes No, non-editable mode
*/
disabled: boolean;
}

View File

@@ -15,5 +15,5 @@
*/
export enum WorkflowRenderKey {
EXECUTE_STATUS_BAR = 'execute_status_bar', // test run 顶部 bar
EXECUTE_STATUS_BAR = 'execute_status_bar', // Test run top bar
}

View File

@@ -77,7 +77,7 @@ export namespace TriggerForm {
export type FormMeta = FormItemMeta[];
// 表单值
// form value
export interface FormValue {
[TriggerFormIsOpenName]?: boolean;
[TriggerFormEventTypeName]?: TriggerFormEventType;

View File

@@ -173,7 +173,7 @@ describe('getLLMModels', () => {
it('should set model_scene when isBindDouyin is true', async () => {
const mockInfo = { schema_json: JSON.stringify(mockSchemaForLLM) };
// 上一个接口有 3s 缓存,需要等待 3s 后再调用
// The previous interface has 3s cache, you need to wait 3s before calling it.
await new Promise(resolve => setTimeout(resolve, 3100));
// Act
@@ -197,7 +197,7 @@ describe('getLLMModels', () => {
const apiError = new Error('API Error');
vi.mocked(developerApi.GetTypeList).mockRejectedValue(apiError);
// 上一个接口有 3s 缓存,需要等待 3s 后再调用
// The previous interface has 3s cache, you need to wait 3s before calling it.
await new Promise(resolve => setTimeout(resolve, 3100));
const models = await getLLMModels({

View File

@@ -63,7 +63,7 @@ describe('llm-utils', () => {
expect(params.modelType).toBe(mockModels[0].model_type);
expect(params.modelName).toBe(mockModels[0].name);
expect(params.generationDiversity).toBe(GenerationDiversity.Balance);
expect(params.temperature).toBe(0.8); // 来自mockModels[0]的balance默认值
expect(params.temperature).toBe(0.8); // Balance default from mockModels [0]
});
});

View File

@@ -27,7 +27,7 @@ import { type NodeData, WorkflowNodeData } from '../entity-datas';
*
* @param node
* @param data
* 给基础类型节点设置节点数据,不要随意修改
* Set the node data for the basic type node, do not modify it at will
*/
export const addBasicNodeData = (
node: FlowNodeEntity,
@@ -39,7 +39,7 @@ export const addBasicNodeData = (
);
const nodeData = nodeDataEntity.getNodeData<keyof NodeData>();
// 在部分节点的 formMeta 方法,会重复执行,因此这里加个检测
// The formMeta method on some nodes will be executed repeatedly, so add a check here
if (!nodeData && meta) {
nodeDataEntity.setNodeData<BasicStandardNodeTypes>({
icon: meta.icon,

View File

@@ -22,7 +22,7 @@ import {
import { type WorkflowNodeRegistry } from '@coze-workflow/base';
/**
* 根据node meta中定义的getLLMModelIdsByNodeJSON方法获取大模型id
* Get the large model id according to the getLLMModelIdsByNodeJSON method defined in node meta
* @param nodeJSON
* @param ids
* @param document
@@ -56,7 +56,7 @@ function getLLMModelIdsByNodeJSON(
}
/**
* 获取模型ids
* Get model ids
* @param json
* @param document
* @returns

View File

@@ -32,7 +32,7 @@ import { DeveloperApi as developerApi } from '@coze-arch/bot-api';
import { getLLMModelIds } from './get-llm-model-ids';
/** 默认的 response format */
/** Default response format value */
export const getDefaultResponseFormat = () => ({
name: RESPONSE_FORMAT_NAME,
label: I18n.t('model_config_response_format'),
@@ -68,20 +68,20 @@ const queryClient = new QueryClient({
});
/**
* 1. 给模型列表中每个模型的 response_format 参数项补全
* 2. 硬编码设置 response_format 的默认值为 JSON
* @param modelList 模型列表
* @returns 补全 response_format 参数后的模型列表
* 1. Complete the response_format parameter items for each model in the model list
* 2. hardcoding settings response_format default value is JSON
* @param modelList
* @Returns List of models after completing response_format parameters
*/
const repairResponseFormatInModelList = (modelList: Model[]) => {
// 找到模型列表中 model_params 的第一个 response_format 参数项
// 这段代码从下边循环中提出来,不需要每次循环计算一次
// Find the first response_format item model_params in the model list
// This code is taken from the following loop and does not need to be evaluated every time
const modelHasResponseFormatItem = modelList
.find(_m => _m.model_params?.find(p => p.name === RESPONSE_FORMAT_NAME))
?.model_params?.find(p => p.name === RESPONSE_FORMAT_NAME);
return modelList.map(m => {
// 兼容后端未刷带的数据,没有 responseFormat 就补上
// Compatible with unflashed data on the backend, it will be added without responseFormat.
const responseFormat = m.model_params?.find(
p => p?.name === RESPONSE_FORMAT_NAME,
) as ModelParameter;
@@ -90,23 +90,23 @@ const repairResponseFormatInModelList = (modelList: Model[]) => {
if (modelHasResponseFormatItem) {
m.model_params?.push(modelHasResponseFormatItem as ModelParameter);
} else {
// 填充一个默认的 response_format 参数
// Fill in a default response_format parameter
m.model_params?.push(getDefaultResponseFormat());
}
}
// 此时再找一次 responseFormat因为上边补全了 responseFormat
// At this point, find the responseFormat again, because the responseFormat is completed above.
const newResponseFormat = m.model_params?.find(
p => p?.name === RESPONSE_FORMAT_NAME,
) as ModelParameter;
// 重置默认值为 JSON
// Reset the default value to JSON
Object.keys(newResponseFormat?.default_val ?? {}).forEach(k => {
newResponseFormat.default_val[k] = ResponseFormat.JSON;
});
if (newResponseFormat) {
// 重置选项,text markdown json 都要支持
// Reset options, text markdown json must be supported
newResponseFormat.options = [
{
label: I18n.t('model_config_history_text'),
@@ -154,8 +154,8 @@ export const getLLMModels = async ({
const resp = await developerApi.GetTypeList(getTypeListParams);
const _modelList: Model[] = resp?.data?.model_list ?? [];
// 从这里开始到 return modelList 全是给后端擦屁股
// 这里有 hard code ,需要把输出格式的默认值设置为 JSON
// From here to return modelList is all about wiping the butt of the backend
// There is hard code here, you need to set the default value of the output format to JSON
return repairResponseFormatInModelList(_modelList);
},
staleTime: 3000,
@@ -166,7 +166,7 @@ export const getLLMModels = async ({
error: error as Error,
eventName: 'api/bot/get_type_list fetch error',
});
// 上报js错误
// Report a js error
captureException(
new Error(
I18n.t('workflow_detail_error_message', {
@@ -174,7 +174,7 @@ export const getLLMModels = async ({
}),
),
);
// 兜底返回空数组
// Return empty array
return [];
}
};

View File

@@ -20,7 +20,7 @@ import { type DTODefine } from '@coze-workflow/base';
export type InputVariableDTO = DTODefine.InputVariableDTO;
/**
* 对输入参数进行排序,然后按照 required 字段进行分组,必填的放最前边
* Sort the input parameters, then group them by required fields, and put the required fields at the front
* @param inputs
* @param groupKey
* @param sortKey
@@ -35,17 +35,17 @@ export const getSortedInputParameters = <
): T[] => {
const processedItems = (inputs || []).map(item => ({
...item,
required: item.required !== undefined ? item.required : false, // 默认设置为 false
required: item.required !== undefined ? item.required : false, // Default setting is false
}));
// 先按照 required 属性分组
// Group by required attributes first
const grouped = groupBy(processedItems, groupKey);
// 在每个组内按照 name 属性进行排序
// Sort by name attribute within each group
const sortedTrueGroup = sortBy(grouped.true, sortKey) || [];
const sortedFalseGroup = sortBy(grouped.false, sortKey) || [];
// 合并 true 分组和 false 分组
// Merge true and false groupings
const mergedArray = [...sortedTrueGroup, ...sortedFalseGroup];
return mergedArray;

View File

@@ -31,7 +31,7 @@ const getDefaultModels = (modelMeta: Model): Record<string, unknown> => {
const k = camelCase(p.name) as string;
const { type } = p;
// 优先取平衡,自定义兜底
// Priority to take the balance, custom bottom line
const defaultValue =
p.default_val[GenerationDiversity.Balance] ??
p.default_val[GenerationDiversity.Customize];
@@ -50,7 +50,7 @@ const getDefaultModels = (modelMeta: Model): Record<string, unknown> => {
};
/**
* 格式化模型数据,根据 modelMeta 将特定字符串转化成数字
* Format model data to convert specific strings to numbers according to modelMeta
* @param model
* @param modelMeta
* @returns

View File

@@ -141,7 +141,7 @@ export namespace nodeUtils {
}
/**
* @deprecated 使用 variableUtils.valueExpressionToDTO)
* @Deprecated using variableUtils.valueExpressionToDTO)
* @param value
* @param nodeFormContext
* @returns
@@ -165,7 +165,7 @@ export namespace nodeUtils {
}
/**
* @deprecated 使用 variableUtils.valueExpressionToDTO
* @Deprecated using variableUtils.valueExpressionToDTO
* @param value
* @returns
*/
@@ -201,7 +201,7 @@ export namespace nodeUtils {
}
/**
* @deprecated 使用 variableUtils.valueExpressionToVO
* @deprecated using variableUtils.valueExpressionToVO
* @param value
* @param nodeFormContext
* @returns
@@ -217,7 +217,7 @@ export namespace nodeUtils {
}
/**
* @deprecated 使用 variableUtils.valueExpressionToVO
* @deprecated using variableUtils.valueExpressionToVO
* @param input
* @returns
*/
@@ -233,7 +233,7 @@ export namespace nodeUtils {
};
}
// 获取batch表单项默认值
// Get the default value of batch order item
export function getBatchInputListFormDefaultValue(index: number) {
return {
name: `item${index}`,
@@ -244,9 +244,9 @@ export namespace nodeUtils {
};
}
// 节点支持批量
// Node support batch
export function getBatchModeFormMeta(isBatchV2: boolean): IFormItemMeta {
// TODO DELETE schemaGray 临时字段,后端灰度刷数据标记,全量后删除
// TODO DELETE schemaGray temporary field, backend grey release brush data mark, delete after full amount
return {
name: 'batchMode',
type: 'string',
@@ -294,7 +294,7 @@ export namespace nodeUtils {
};
}
// formValueToDto & dtoToFormValue 只迁移了api-node中对inputParameters、batch的适配
// formValueToDto & dtoToFormValue only migrates the adaptation of inputParameters and batch in api-node
export function formValueToDto(value: any, context) {
const inputParams = get(value, INPUT_PARAMS_PATH);
const formattedInputParams = inputParams

View File

@@ -15,10 +15,10 @@
*/
/**
* 为什么要这么维护 triggerId
* 新的流程 fetchStartNodeTriggerFormValue 时没有 triggerId ,初次保存后,后端返回 triggerId
* 已经保存过的流程, fetchStartNodeTriggerFormValue 时,会返回 triggerId
* 获取时机不同,把 triggerId 硬塞到 formData 中比较麻烦,所以直接维护在 cacheTriggerId
* Why maintain triggerId so much?
* The new process fetchStartNodeTriggerFormValue without triggerId, after the initial save, the backend returns triggerId
* The saved process, when fetchStartNodeTriggerFormValue, will return triggerId
* The acquisition time is different, and it is more troublesome to hard-plug the triggerId into formData, so it is directly maintained in the cacheTriggerId.
*/
const cacheTriggerId: Record<string, string> = {};
export const setTriggerId = (wfId: string, triggerId: string) => {

View File

@@ -19,7 +19,7 @@ import { I18n } from '@coze-arch/i18n';
import { codeEmptyValidator } from '../code-empty-validator';
// 模拟I18n.t方法
// Simulation I18n.t method
vi.mock('@coze-arch/i18n', () => ({
I18n: { t: vi.fn(key => `translated_${key}`) },
}));

View File

@@ -20,7 +20,7 @@ import { I18n } from '@coze-arch/i18n';
import { nodeMetaValidator } from '../node-meta-validator';
// 模拟 I18n.t 方法
// Simulation I18n.t method
vi.mock('@coze-arch/i18n', () => ({
I18n: { t: vi.fn(key => `translated_${key}`) },
}));
@@ -98,7 +98,7 @@ describe('nodeMetaValidator', () => {
mockNodesService.getAllNodes.mockReturnValue([
{ id: 'node1', title: 'ExistingTitle' },
{ id: 'node2', title: 'AnotherNode' },
{ id: 'node2', title: 'ExistingTitle' }, // 这里模拟一个重复的标题
{ id: 'node2', title: 'ExistingTitle' }, // Here a repeating title is simulated.
]);
const result = nodeMetaValidator({
value: { title: 'ExistingTitle' },

View File

@@ -19,7 +19,7 @@ import { describe, it, vi, expect } from 'vitest';
import { questionOptionValidator } from '../question-option-validator';
// 模拟 I18n.t 方法
// Simulation I18n.t method
vi.mock('@coze-arch/i18n', () => ({
I18n: { t: vi.fn(key => `translated_${key}`) },
}));

View File

@@ -35,7 +35,7 @@ interface Issue {
}
/**
* 输入树校验器
* input tree validator
*/
export class InputTreeValidator {
private node: FlowNodeEntity;
@@ -47,7 +47,7 @@ export class InputTreeValidator {
}
/**
* 校验函数
* check function
* @param inputalues
* @reurns
*/
@@ -58,7 +58,7 @@ export class InputTreeValidator {
}
/**
* 校验多个输入
* Validate multiple inputs
* @param inputValues
* @param path
* @returns
@@ -90,13 +90,13 @@ export class InputTreeValidator {
});
const children = inputValues[i]?.children || [];
// 递归检查子节点
// Recursively check sub-node
this.validateInputValues(children, path.concat(i, 'children'));
}
}
/**
* 输入名称校验
* input name validation
*/
private validateName({ value, values }) {
if (!value) {
@@ -104,12 +104,12 @@ export class InputTreeValidator {
}
const names = values.map(v => v.name).filter(Boolean);
// 名称格式校验
// name format verification
if (!VARIABLE_NAME_REGEX.test(value)) {
return I18n.t('workflow_detail_node_error_format');
}
// 重名校验
// duplicate name verification
const foundSames = names.filter((name: string) => name === value);
return foundSames.length > 1
@@ -118,12 +118,12 @@ export class InputTreeValidator {
}
/**
* 输入值校验
* input value validation
*/
private validateInput({ value }) {
const { variableValidationService } = this.playgroundContext;
// 校验空值
// check null value
if (ValueExpression.isEmpty(value)) {
return I18n.t('workflow_detail_node_error_empty');
}
@@ -160,7 +160,7 @@ export function inputTreeValidator(params: ValidatorProps<InputValueVO>) {
ctx.addIssue({
path: issue.path,
message: issue.message,
// FIXME: 表单校验底层依赖了 validation / code去掉就跑不通了
// FIXME: The underlying layer of form validation relies on validation/code, so it won't work if you remove it.
validation: 'regex',
code: 'invalid_string',
});

View File

@@ -43,7 +43,7 @@ export const jsonSchemaValidator = (
return valid;
// eslint-disable-next-line @coze-arch/use-error-in-catch
} catch (error) {
// parse失败说明不是合法值
// Parse failure indicates that it is not a legal value
return false;
}
};

View File

@@ -59,7 +59,7 @@ export const nodeMetaValidator = ({
return nodes?.length > 1;
}
// 增加节点名重复校验
// Add Node Name Duplicate Validation
const schema = NodeMetaSchema.refine(
({ title }: NodeMeta) => !isTitleRepeated(title),
{

View File

@@ -19,7 +19,7 @@ import { ViewVariableType } from '@coze-workflow/base';
import { I18n } from '@coze-arch/i18n';
import { jsonSchemaValidator } from '../json-schema-validator';
// 定义节点Schema
// Define Node Schema
const OutputTreeNodeSchema: ZodSchema<any> = z.lazy(() =>
z
.object({
@@ -41,7 +41,7 @@ const OutputTreeNodeSchema: ZodSchema<any> = z.lazy(() =>
export const OutputTreeSchema = z.array(OutputTreeNodeSchema);
// 定义一个辅助函数,用于查找重复名字的节点并返回错误路径
// Define a helper function to find nodes with duplicate names and return the error path
const findDuplicates = (nodes, path = []) => {
const seen = new Set();
let result: {
@@ -52,7 +52,7 @@ const findDuplicates = (nodes, path = []) => {
for (let i = 0; i < nodes.length; i++) {
const { name } = nodes[i];
if (seen.has(name)) {
// 找到重复项时返回路径和错误信息
// Returns paths and error messages when duplicates are found
result = {
// @ts-expect-error -- linter-disable-autofix
path: path.concat(i, 'name'),
@@ -62,7 +62,7 @@ const findDuplicates = (nodes, path = []) => {
}
seen.add(name);
if (nodes[i].children) {
// 递归检查子节点
// Recursively check sub-node
const found = findDuplicates(
nodes[i].children,
// @ts-expect-error -- linter-disable-autofix
@@ -78,35 +78,35 @@ const findDuplicates = (nodes, path = []) => {
return result;
};
// 定义同级命名唯一的树结构Schema
// Define a sibling-named unique tree structure schema
export const OutputTreeUniqueNameSchema = z
.array(OutputTreeNodeSchema)
.refine(
data => {
// 使用自定义函数进行检查
// Check with a custom function
const duplicate = findDuplicates(data);
return !duplicate;
},
data => {
// 使用自定义函数进行检查
// Check with a custom function
const duplicate = findDuplicates(data);
return {
path: duplicate.path,
message: duplicate.message,
// FIXME: 表单校验底层依赖了 validation / code去掉就跑不通了
// FIXME: The underlying layer of form validation relies on validation/code, so it won't work if you remove it.
validation: 'regex',
code: 'invalid_string',
};
},
)
.superRefine((data, ctx) => {
// 使用自定义函数进行检查
// Check with a custom function
const issues = checkObjectDefaultValue(data);
issues.forEach(issue => {
ctx.addIssue({
path: issue.path,
message: issue.message,
// FIXME: 表单校验底层依赖了 validation / code去掉就跑不通了
// FIXME: The underlying layer of form validation relies on validation/code, so it won't work if you remove it.
validation: 'regex',
code: 'invalid_string',
});
@@ -128,15 +128,15 @@ const checkObjectDefaultValue = nodes => {
continue;
}
if (!jsonSchemaValidator(defaultValue, nodes[i])) {
// 找到重复项时返回路径和错误信息
// Returns paths and error messages when duplicates are found
result.push({
path: [i, 'defaultValue'],
message: I18n.t('workflow_debug_wrong_json'),
});
}
// json 类型只检查第一层,不需要递归检查
// The JSON type only checks the first layer, no recursive check is required
}
return result;
};
// 导出类型别名
// export type alias
export type OutputTree = z.infer<typeof OutputTreeSchema>;

View File

@@ -18,7 +18,7 @@ import { z, ZodIssueCode } from 'zod';
import { I18n } from '@coze-arch/i18n';
import { type ValidatorProps } from '@flowgram-adapter/free-layout-editor';
// 自定义验证器,检查数组是否为空,并且没有重复的值
// Custom validator to check if the array is empty and there are no duplicate values
const nonEmptyUniqueArray = z
.array(
z.object({
@@ -29,7 +29,7 @@ const nonEmptyUniqueArray = z
const seenValues = new Set();
val.forEach((item, idx) => {
// 检查非空
// check non-empty
if (item.name.trim() === '') {
ctx.addIssue({
code: ZodIssueCode.custom,
@@ -42,7 +42,7 @@ const nonEmptyUniqueArray = z
});
}
// 检查重复
// Check for duplicates
if (seenValues.has(item.name)) {
ctx.addIssue({
code: ZodIssueCode.custom,

View File

@@ -52,7 +52,7 @@ export const settingOnErrorValidator = ({
}
return true;
}
// json 合法性校验
// json legitimacy check
const schemeParesd = SettingOnErrorSchema.refine(
settingOnError => isJSONVerified(settingOnError),
{

View File

@@ -34,7 +34,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
protected jsonFormats: WorkflowJSONFormatContribution[] = [];
/**
* 从数据加载
* load from data
* @param json
*/
fromJSON(json: Partial<WorkflowJSON>, fireRender = true): void {
@@ -51,7 +51,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
private _formatCache = new Map<string | number | symbol, any>();
/**
* 转换 json
* Convert json
* @param json
* @param formatKey
* @param args
@@ -76,7 +76,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
}
/**
* 创建流程节点
* Create process node
* @param json
*/
createWorkflowNode(
@@ -95,7 +95,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
toNodeJSON(node: WorkflowNodeEntity): WorkflowNodeJSON {
const json = super.toNodeJSON(node);
// 格式化
// format
const formattedJSON = this.formatWorkflowJSON<WorkflowNodeJSON>(
json,
'formatNodeOnSubmit',
@@ -106,7 +106,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
}
/**
* 导出数据
* export data
*/
toJSON(): WorkflowJSON {
const rootJSON = this.toNodeJSON(this.root);
@@ -131,7 +131,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
}
/**
* 拍平树形json结构将结构信息提取到map
* Flatten the tree-shaped JSON structure and extract the structure information to the map.
*/
private flatJSON(json: Partial<WorkflowJSON> = { nodes: [], edges: [] }): {
flattenJSON: WorkflowJSON;
@@ -151,7 +151,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
nodeBlocks.set(FlowNodeBaseType.ROOT, rootBlockIDs);
nodeEdges.set(FlowNodeBaseType.ROOT, rootEdgeIDs);
// 如需支持多层结构,以下部分改为递归
// To support multi-layer structures, the following section is changed to recursive
rootNodes.forEach(nodeJSON => {
const { blocks, edges } = nodeJSON;
if (blocks) {
@@ -188,7 +188,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
}
/**
* 对JSON进行分层
* Layering JSON
*/
private nestJSON(
flattenJSON: WorkflowJSON,
@@ -208,7 +208,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
nodeEdges.get(FlowNodeBaseType.ROOT) ?? [],
);
// 构造缓存
// Construct cache
flattenJSON.nodes.forEach(nodeJSON => {
nodeMap.set(nodeJSON.id, nodeJSON);
});
@@ -218,12 +218,12 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
edgeMap.set(edgeID, edgeJSON);
});
// 恢复层级数据
// Restore hierarchical data
flattenJSON.nodes.forEach(nodeJSON => {
if (rootBlockSet.has(nodeJSON.id)) {
nestJSON.nodes.push(nodeJSON);
}
// 恢复blocks
// Recovery blocks
if (nodeBlocks.has(nodeJSON.id)) {
const blockIDs = nodeBlocks.get(nodeJSON.id)!;
const blockJSONs: WorkflowNodeJSON[] = blockIDs
@@ -231,7 +231,7 @@ export class WorkflowDocumentWithFormat extends WorkflowDocument {
.filter(Boolean);
nodeJSON.blocks = blockJSONs;
}
// 恢复edges
// Restore edges
if (nodeEdges.has(nodeJSON.id)) {
const edgeIDs = nodeEdges.get(nodeJSON.id)!;
const edgeJSONs: WorkflowEdgeJSON[] = edgeIDs

View File

@@ -48,7 +48,7 @@ import {
} from './typings';
/**
* 全局转换表单数据,这里主要处理变量生成逻辑
* Transform form data globally, where variable generation logic is primarily handled
*/
@injectable()
export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
@@ -67,7 +67,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
/**
* 转换节点变量
* Convert node variable
* @param json
* @protected
*/
@@ -93,7 +93,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
/**
* 兼容仅有单个batch变量的历史数据
* Compatible with historical data with only a single batch variable
*/
protected transformBatchVariable(
json: WorkflowNodeJSON,
@@ -104,21 +104,21 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
const input: ValueExpressionDTO = get(json.data, 'inputs.batch.inputList');
if (!input || isEmpty(input)) {
// 无需兼容
// No compatibility required
return;
}
const inputList: BatchDTOInputList = {
name: 'item', // 按照PRD写死即可
name: 'item', // According to PRD, just write it dead.
input,
};
// 在json中填充新数据
// Filling in new data in JSON
json.data.inputs.batch.inputLists = [inputList];
// 删掉旧数据
// Delete old data
delete json.data.inputs.batch.inputList;
}
/**
* 修复变量引用逻辑
* Fix variable reference logic
* @param json
* @param doc
* @protected
@@ -148,7 +148,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
/**
* 处理节点元数据 & 静态文案
* Processing node metadata & static copy
* @param json
* @param doc
* @protected
@@ -157,7 +157,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
json: WorkflowNodeJSON,
doc: WorkflowDocument,
): void {
// API 插件节点暂时不需要处理文案
// The API plug-in node does not need to process copywriting for the time being.
if (
json?.type &&
[StandardNodeType.Api, StandardNodeType.SubWorkflow].includes(
@@ -168,7 +168,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
const nodeMeta = get(json, 'data.nodeMeta');
// 拉取的最新配置数据
// Latest configuration data pulled
const meta = this.playgroundContext.getNodeTemplateInfoByType(json.type);
if (
@@ -177,7 +177,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
meta &&
typeof meta === 'object'
) {
// 根据后端配置确定,不由用户控制节点元数据
// Determined according to the backend configuration, the node metadata is not controlled by the user
const staticMeta = pick(meta, ['icon', 'subTitle']);
set(json, 'data.nodeMeta', {
@@ -188,7 +188,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
/**
* 初始化节点
* initialize node
* @param json
* @param doc
* @param isClone
@@ -198,7 +198,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
doc: WorkflowDocument,
isClone?: boolean,
): WorkflowNodeJSON {
// 非 clone 在 formatOnInit 已经触发
// Non-cloning has been triggered in formatOnInit
if (!isClone) {
return json;
}
@@ -208,7 +208,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}
/**
* 提交节点
* commit node
* @param json
* @param doc
*/
@@ -222,7 +222,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
).meta;
const variablesMeta = this.getVariablesMeta(json.type, doc);
if (json.data) {
// 转换 output
// Convert output
variablesMeta.outputsPathList!.forEach(outputsPath => {
const variableMetas = get(json.data, outputsPath) as ViewVariableMeta[];
if (variableMetas && Array.isArray(variableMetas)) {
@@ -235,7 +235,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
});
}
});
// 转换 input
// Conversion input
variablesMeta.inputsPathList!.forEach(inputsPath => {
const inputValues: InputValueVO[] = get(
json.data,
@@ -254,7 +254,7 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
}),
);
});
// 过滤掉空值
// Filter out null values
set(json.data, inputsPath, inputValues.filter(Boolean));
}
});
@@ -263,27 +263,27 @@ export class WorkflowJSONFormat implements WorkflowJSONFormatContribution {
return json;
}
/**
* 初始化时候转换变量数据
* Convert variable data during initialization
* @param json
* @param document
*/
formatOnInit(json: WorkflowJSON, document: WorkflowDocument): WorkflowJSON {
// Step0: batch 兼容处理
// Step0: batch compatible processing
json.nodes.forEach(node => this.transformBatchVariable(node, document));
// Step1: 创建输出变量
// Step1: Create an output variable
json.nodes.forEach(node => this.formatOutputVariables(node, document));
// Step2: 处理input中值转换
// Step2: Handle input median conversion
json.nodes.forEach(node => this.formatInputVariables(node, document));
// Step3: 处理节点 description & subTitle 等静态文案数据 (不从落库数据中取,而是根据最新节点数据中获取)
// Step3: Process static copy data such as node description & subTitle (not from the drop database data, but from the latest node data)
json.nodes.forEach(node => this.formatNodeMeta(node, document));
return json;
}
/**
* 提交时候转换变量数据
* Convert variable data at commit time
* @param json
*/
formatOnSubmit(json: WorkflowJSON, document: WorkflowDocument): WorkflowJSON {

View File

@@ -31,7 +31,7 @@ export const WorkflowNodesContainerModule = new ContainerModule(
bindContributions(bind, WorkflowJSONFormat, [
WorkflowJSONFormatContribution,
]);
// 这里兼容老的 画布 document
// Compatible with old canvas documents
bind(WorkflowDocumentWithFormat).toSelf().inSingletonScope();
rebind(WorkflowDocument).toService(WorkflowDocumentWithFormat);
},