feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { uniqBy } from 'lodash-es';
|
||||
import { type PropertyJSON } from '@flowgram-adapter/free-layout-editor';
|
||||
import { type RefExpression } from '@coze-workflow/base/types';
|
||||
|
||||
export interface InputItem {
|
||||
name: string;
|
||||
input: RefExpression;
|
||||
}
|
||||
|
||||
export const uniqInputs = (inputs?: InputItem[]): InputItem[] =>
|
||||
uniqBy(
|
||||
(inputs || []).filter(_input => _input && _input?.name),
|
||||
_child => _child?.name,
|
||||
);
|
||||
|
||||
export const uniqProperties = (properties?: PropertyJSON[]): PropertyJSON[] =>
|
||||
uniqBy(
|
||||
(properties || []).filter(_input => _input && _input?.key),
|
||||
_child => _child?.key,
|
||||
);
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ASTFactory } from '@flowgram-adapter/free-layout-editor';
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { ValueExpressionType } from '../../typings';
|
||||
import { createRefExpression } from '../../core/extend-ast/custom-key-path-expression';
|
||||
import { type InputItem, uniqInputs, uniqProperties } from './common';
|
||||
interface ValueType {
|
||||
inputParameters?: InputItem[];
|
||||
variableParameters?: InputItem[];
|
||||
}
|
||||
|
||||
export const parseLoopInputsByViewVariableMeta = (
|
||||
nodeId: string,
|
||||
value: ValueType,
|
||||
) => {
|
||||
const { inputParameters, variableParameters } = value || {};
|
||||
const batchProperties = uniqInputs(inputParameters).map(_input =>
|
||||
ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
meta: {
|
||||
label: `item (in ${_input?.name})`,
|
||||
},
|
||||
initializer: ASTFactory.createEnumerateExpression({
|
||||
enumerateFor: createRefExpression({
|
||||
keyPath: _input?.input?.content?.keyPath || [],
|
||||
rawMeta: _input?.input?.rawMeta,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
const variableProperties = uniqInputs(variableParameters).map(_input => {
|
||||
// 没有 rawMeta 时,可能是历史数据,走下面的兜底逻辑
|
||||
if (_input?.input?.rawMeta?.type) {
|
||||
return ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
meta: {
|
||||
mutable: true,
|
||||
},
|
||||
initializer: createRefExpression({
|
||||
keyPath: _input?.input?.content?.keyPath || [],
|
||||
rawMeta: _input?.input?.rawMeta,
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (_input?.input?.type === ValueExpressionType.REF) {
|
||||
return ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
meta: {
|
||||
mutable: true,
|
||||
},
|
||||
// 直接引用变量
|
||||
initializer: ASTFactory.createKeyPathExpression({
|
||||
keyPath: _input?.input?.content?.keyPath || [],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
meta: {
|
||||
mutable: true,
|
||||
},
|
||||
type: ASTFactory.createString(),
|
||||
});
|
||||
});
|
||||
|
||||
const indexProperties = [
|
||||
ASTFactory.createProperty({
|
||||
key: 'index',
|
||||
type: ASTFactory.createInteger(),
|
||||
}),
|
||||
];
|
||||
|
||||
const properties = uniqProperties([
|
||||
...batchProperties,
|
||||
...indexProperties,
|
||||
...variableProperties,
|
||||
]);
|
||||
|
||||
return [
|
||||
ASTFactory.createVariableDeclaration({
|
||||
key: `${nodeId}.locals`,
|
||||
type: ASTFactory.createObject({
|
||||
properties,
|
||||
}),
|
||||
}),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* 循环输入变量同步
|
||||
*/
|
||||
export const provideLoopInputsVariables: VariableProviderAbilityOptions = {
|
||||
key: 'provide-loop-input-variables',
|
||||
namespace: '/node/locals',
|
||||
private: true,
|
||||
scope: 'private',
|
||||
parse(value: ValueType, context) {
|
||||
return parseLoopInputsByViewVariableMeta(context.node.id, value);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
import { ASTFactory } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { createWrapArrayExpression } from '../../core/extend-ast/wrap-array-expression';
|
||||
import { type InputItem, uniqInputs } from './common';
|
||||
|
||||
export const parseLoopOutputsByViewVariableMeta = (
|
||||
nodeId: string,
|
||||
value: InputItem[],
|
||||
) => {
|
||||
const properties = uniqInputs(value || []).map(_input => {
|
||||
const keyPath = _input?.input?.content?.keyPath;
|
||||
// 如果选择的是 Loop 的 Variable 内的变量
|
||||
if (keyPath?.[0] === nodeId) {
|
||||
return ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
// 直接引用变量
|
||||
initializer: ASTFactory.createKeyPathExpression({
|
||||
keyPath: _input?.input?.content?.keyPath || [],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return ASTFactory.createProperty({
|
||||
key: _input?.name,
|
||||
// 输出类型包一层 Array
|
||||
initializer: createWrapArrayExpression({
|
||||
keyPath: _input?.input?.content?.keyPath || [],
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
return [
|
||||
ASTFactory.createVariableDeclaration({
|
||||
key: `${nodeId}.outputs`,
|
||||
type: ASTFactory.createObject({
|
||||
properties,
|
||||
}),
|
||||
}),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* 循环输出变量同步
|
||||
*/
|
||||
export const provideLoopOutputsVariables: VariableProviderAbilityOptions = {
|
||||
key: 'provide-loop-output-variables',
|
||||
namespace: '/node/outputs',
|
||||
private: false,
|
||||
scope: 'public',
|
||||
parse(value, context) {
|
||||
return parseLoopOutputsByViewVariableMeta(context.node.id, value);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ASTFactory,
|
||||
ASTKind,
|
||||
type ObjectType,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
import { type EffectOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { createEffectFromVariableProvider } from '../../utils/variable-provider';
|
||||
import { setValueIn } from '../../utils/form';
|
||||
import { type RefExpression } from '../../typings';
|
||||
import {
|
||||
createMergeGroupExpression,
|
||||
MergeStrategy,
|
||||
} from '../../core/extend-ast/merge-group-expression';
|
||||
import { createRefExpression } from '../../core/extend-ast/custom-key-path-expression';
|
||||
import { WorkflowVariableFacadeService } from '../../core';
|
||||
|
||||
interface MergeGroup {
|
||||
name: string;
|
||||
variables: RefExpression[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并组变量同步
|
||||
*/
|
||||
export const provideMergeGroupVariables: VariableProviderAbilityOptions = {
|
||||
key: 'provide-merge-group-variables',
|
||||
namespace: '/node/outputs',
|
||||
parse(value: MergeGroup[], context) {
|
||||
const nodeId = context.node.id;
|
||||
|
||||
return [
|
||||
ASTFactory.createVariableDeclaration({
|
||||
key: `${nodeId}.outputs`,
|
||||
type: ASTFactory.createObject({
|
||||
properties: value?.map(_item =>
|
||||
ASTFactory.createProperty({
|
||||
key: _item?.name,
|
||||
initializer: createMergeGroupExpression({
|
||||
mergeStrategy: MergeStrategy.FirstNotEmpty,
|
||||
expressions: _item.variables.map(_v =>
|
||||
createRefExpression({
|
||||
keyPath: _v?.content?.keyPath || [],
|
||||
rawMeta: _v?.rawMeta,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
}),
|
||||
];
|
||||
},
|
||||
onInit(ctx) {
|
||||
const facadeService = ctx.node.getService(WorkflowVariableFacadeService);
|
||||
|
||||
return ctx.scope.ast.subscribe(() => {
|
||||
// 监听输出变量变化,回填到表单的 outputs
|
||||
const outputVariable = ctx.scope.output.variables[0];
|
||||
if (outputVariable?.type?.kind === ASTKind.Object) {
|
||||
const { properties } = outputVariable.type as ObjectType;
|
||||
|
||||
const nextOutputs = properties
|
||||
.map(
|
||||
_property =>
|
||||
// OutputTree 组件中,所有树节点的 key 需要保证是唯一的
|
||||
facadeService.getVariableFacadeByField(_property)
|
||||
.viewMetaWithUniqKey,
|
||||
)
|
||||
.filter(Boolean);
|
||||
|
||||
setValueIn(ctx.node, 'outputs', nextOutputs);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const provideMergeGroupVariablesEffect: EffectOptions[] =
|
||||
createEffectFromVariableProvider(provideMergeGroupVariables);
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
import { FlowNodeFormData } from '@flowgram-adapter/free-layout-editor';
|
||||
import { Disposable } from '@flowgram-adapter/common';
|
||||
|
||||
import { parseNodeBatchByInputList } from '../../core';
|
||||
|
||||
export const provideNodeBatchVariables: VariableProviderAbilityOptions = {
|
||||
key: 'provide-node-batch-variables',
|
||||
namespace: '/node/locals',
|
||||
scope: 'private',
|
||||
parse(value, context) {
|
||||
const batchMode =
|
||||
context.formItem?.formModel.getFormItemValueByPath('/batchMode') ||
|
||||
context.formItem?.formModel.getFormItemValueByPath('/inputs/batchMode');
|
||||
|
||||
if (batchMode !== 'batch') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return parseNodeBatchByInputList(context.node.id, value);
|
||||
},
|
||||
onInit(context) {
|
||||
const formData = context.node.getData(FlowNodeFormData);
|
||||
if (!formData) {
|
||||
return Disposable.create(() => null);
|
||||
}
|
||||
|
||||
return formData.onDetailChange(_detail => {
|
||||
if (_detail.path.includes('/batchMode')) {
|
||||
context.triggerSync();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { parseNodeOutputByViewVariableMeta } from '../../core';
|
||||
|
||||
export const provideNodeOutputVariables: VariableProviderAbilityOptions = {
|
||||
key: 'provide-node-output-variables',
|
||||
namespace: '/node/outputs',
|
||||
parse(value, context) {
|
||||
return parseNodeOutputByViewVariableMeta(context.node.id, value);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user