feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
export { ModelSettingField } from './model-setting-field';
export { ReferencesField } from './references-field';
export { PromptField } from './prompt-field';

View File

@@ -0,0 +1,51 @@
/*
* 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 { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
import thumbnail8 from '../../assets/8.png';
import thumbnail7 from '../../assets/7.jpg';
import thumbnail6 from '../../assets/6.jpg';
import thumbnail5 from '../../assets/5.jpg';
import thumbnail4 from '../../assets/4.jpg';
import thumbnail3 from '../../assets/3.jpg';
import thumbnail2 from '../../assets/2.jpg';
import thumbnail1 from '../../assets/1.jpg';
const thumbnails = [
thumbnail1,
thumbnail2,
thumbnail3,
thumbnail4,
thumbnail5,
thumbnail6,
thumbnail7,
thumbnail8,
];
export function createModelOptions() {
let models = [1, 8, 2, 3, 4, 5, 6, 7];
if (IS_OVERSEA) {
models = models.filter(model => ![6].includes(model));
}
return models.map(model => ({
label: I18n.t(`Imageflow_model${model}` as I18nKeysNoOptionsType),
value: model,
thumbnail: thumbnails[model - 1],
}));
}

View File

@@ -0,0 +1,17 @@
/*
* 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.
*/
export { ModelSettingField } from './model-setting-field';

View File

@@ -0,0 +1,24 @@
/*
* 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 { ImageModelSelectField } from '@/node-registries/common/components';
import { type FieldProps } from '@/form';
import { createModelOptions } from './create-model-options';
export const ModelField = (props: Omit<FieldProps, 'children'>) => (
<ImageModelSelectField options={createModelOptions()} {...props} />
);

View File

@@ -0,0 +1,49 @@
/*
* 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 { I18n } from '@coze-arch/i18n';
import { Section, SliderField, type FieldProps } from '@/form';
import { RatioField } from './ratio-field';
import { ModelField } from './model-field';
export const ModelSettingField = ({ name }: Pick<FieldProps, 'name'>) => (
<Section title={I18n.t('Imageflow_model_deploy')}>
<div className="flex flex-col gap-[8px]">
<ModelField
name={`${name}.model`}
layout="vertical"
label={I18n.t('Imageflow_model')}
/>
<RatioField
name={`${name}.custom_ratio`}
layout="vertical"
label={I18n.t('Imageflow_ratio')}
tooltip={I18n.t('Imageflow_size_range')}
/>
<SliderField
name={`${name}.ddim_steps`}
layout="vertical"
label={I18n.t('Imageflow_generate_standard')}
tooltip={I18n.t('imageflow_generation_desc1')}
min={1}
max={40}
step={1}
/>
</div>
</Section>
);

View File

@@ -0,0 +1,92 @@
/*
* 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 { SizeSelect } from '@coze-workflow/components';
import { withField, useField } from '@/form';
const ratioOptions = [
{
label: '16:9 (1024*576)',
value: {
width: 1024,
height: 576,
},
},
{
label: '3:2 (1024*682)',
value: {
width: 1024,
height: 682,
},
},
{
label: '4:3 (1024*768)',
value: {
width: 1024,
height: 768,
},
},
{
label: '1:1 (1024*1024)',
value: {
width: 1024,
height: 1024,
},
},
{
label: '3:4 (768*1024)',
value: {
width: 768,
height: 1024,
},
},
{
label: '2:3 (682*1024)',
value: {
width: 682,
height: 1024,
},
},
{
label: '9:16 (576*1024)',
value: {
width: 576,
height: 1024,
},
},
];
export const RatioField = withField(() => {
const { value, readonly, onChange } = useField<{
width?: number;
height?: number;
}>();
return (
<SizeSelect
value={value}
onChange={onChange}
readonly={readonly}
minWidth={512}
maxWidth={1536}
minHeight={512}
maxHeight={1536}
options={ratioOptions}
layoutStyle="vertical"
/>
);
});

View File

@@ -0,0 +1,57 @@
/*
* 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 { I18n } from '@coze-arch/i18n';
import { ExpressionEditorField } from '@/node-registries/common/components';
import { withField, useField, Section } from '@/form';
export const PromptField = withField(
() => {
const { name } = useField();
const promptName = `${name}.prompt`;
const negativePromptName = `${name}.negative_prompt`;
// 保障和之前节点testID不变
const promptTestIDSuffix = name.replace('inputs.', '');
const negativePromptTestIDSuffix = name.replace('inputs.', '');
return (
<Section
title={I18n.t('Imageflow_prompt')}
tooltip={I18n.t('imageflow_generation_desc4')}
>
<ExpressionEditorField
name={promptName}
testIDSuffix={promptTestIDSuffix}
label={I18n.t('Imageflow_positive')}
placeholder={I18n.t('Imageflow_positive_placeholder')}
required={true}
layout="vertical"
/>
<ExpressionEditorField
name={negativePromptName}
testIDSuffix={negativePromptTestIDSuffix}
label={I18n.t('Imageflow_negative')}
placeholder={I18n.t('Imageflow_negative_placeholder')}
layout="vertical"
/>
</Section>
);
},
{
hasFeedback: false,
},
);

View File

@@ -0,0 +1,98 @@
/*
* 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 { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
import thumbnail7 from '../../assets/reference-7.png';
import thumbnail6 from '../../assets/reference-6.jpg';
import thumbnail5 from '../../assets/reference-5.jpg';
import thumbnail4 from '../../assets/reference-4.jpg';
import thumbnail3 from '../../assets/reference-3.jpg';
import thumbnail2 from '../../assets/reference-2.jpg';
import thumbnail1 from '../../assets/reference-1.jpg';
const thumbnails = [
thumbnail1,
thumbnail2,
thumbnail3,
thumbnail4,
thumbnail5,
thumbnail6,
thumbnail7,
];
export function createPreprocessorOptions({
currentPreprocessor,
allSelectedPreprocessor = [],
}: {
currentPreprocessor?: number;
allSelectedPreprocessor: number[];
}) {
const options = [1, 2, 3, 4, 5, 7, 6].map(index => ({
label: I18n.t(`Imageflow_reference${index}` as I18nKeysNoOptionsType),
value: index,
tooltip: I18n.t(
`imageflow_reference_desc${index}` as I18nKeysNoOptionsType,
),
thumbnail: thumbnails[index - 1],
disabled: isPreprocessorDisabled({
currentItemPreprocessor: currentPreprocessor,
currentOptionPreprocessor: index,
allSelectedPreprocessor,
}),
}));
return options;
}
function isPreprocessorDisabled({
currentItemPreprocessor,
currentOptionPreprocessor,
allSelectedPreprocessor,
}: {
currentItemPreprocessor?: number;
currentOptionPreprocessor: number;
allSelectedPreprocessor: number[];
}) {
let disabled = false;
// 如果当前选项的预处理器已经被当前项选中 从allSelectedPreprocessor中移除
allSelectedPreprocessor = allSelectedPreprocessor.filter(
item =>
!(
item === currentItemPreprocessor &&
currentItemPreprocessor === currentOptionPreprocessor
),
);
// 不能添加相同的模型
if (allSelectedPreprocessor.includes(currentOptionPreprocessor)) {
disabled = true;
}
// 1到4编号最多只能出现两个 4以上编号的模型不做限制
const group = [1, 2, 3, 4];
if (group.includes(currentOptionPreprocessor)) {
const isPreprocessorGroup =
allSelectedPreprocessor.filter(item => group.includes(item)).length === 2;
if (isPreprocessorGroup) {
disabled = true;
}
}
return disabled;
}

View File

@@ -0,0 +1,17 @@
/*
* 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.
*/
export { ReferencesField } from './references-field';

View File

@@ -0,0 +1,126 @@
/*
* 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 { useMemo } from 'react';
import { ViewVariableType } from '@coze-workflow/variable';
import { I18n } from '@coze-arch/i18n';
import { ValueExpressionInputField } from '@/node-registries/common/fields';
import { ImageModelSelectField } from '@/node-registries/common/components';
import {
withFieldArray,
Section,
FieldArrayList,
FieldArrayItem,
ColumnTitles,
useFieldArray,
InputNumberField,
AddButton,
} from '@/form';
import { type Reference } from '../../types';
import { DEFAULT_REFERENCE } from '../../constants';
import { createPreprocessorOptions } from './create-preprocessor-options';
export const ReferencesField = withFieldArray(() => {
const { name, value, append, remove } = useFieldArray<Reference>();
const preprocessors = useMemo(
() =>
value
?.map(item => item.preprocessor)
.filter(item => item !== undefined) || [],
[value],
);
return (
<Section
title={I18n.t('Imageflow_reference_image')}
actions={[
<AddButton
key="add"
onClick={() => append(DEFAULT_REFERENCE)}
disabled={value && value?.length >= 5}
/>,
]}
>
<ColumnTitles
columns={[
{
label: I18n.t('Imageflow_reference_info1'),
style: {
width: 120,
},
},
{
label: I18n.t('Imageflow_reference_info2'),
style: {
width: 150,
},
},
{
label: I18n.t('Imageflow_reference_info3'),
},
]}
/>
<FieldArrayList>
{value?.map((item, index) => {
const preprocessorName = `${name}.${index}.preprocessor`;
const urlName = `${name}.${index}.url`;
const weightName = `${name}.${index}.weight`;
const options = createPreprocessorOptions({
currentPreprocessor: item.preprocessor,
allSelectedPreprocessor: preprocessors,
});
return (
<FieldArrayItem onRemove={() => remove(index)}>
<div className="flex-[2_1_0%] min-w-[0px] max-w-[120px]">
<ImageModelSelectField
name={preprocessorName}
options={options}
showClear={true}
placeholder={I18n.t('Imageflow_mode_choose')}
/>
</div>
<div className="w-[150px]">
<ValueExpressionInputField
name={urlName}
inputType={ViewVariableType.Image}
selectStyle={{
width: 80,
}}
/>
</div>
<div className="w-full">
<InputNumberField
name={weightName}
min={0}
max={1}
step={0.1}
/>
</div>
</FieldArrayItem>
);
})}
</FieldArrayList>
</Section>
);
});

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
export const DEFAULT_REFERENCE = {
weight: 0.7,
};

View File

@@ -0,0 +1,149 @@
/*
* 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 { nanoid } from 'nanoid';
import { get, set } from 'lodash-es';
import {
ValidateTrigger,
type FormMetaV2,
} from '@flowgram-adapter/free-layout-editor';
import { ViewVariableType } from '@coze-workflow/base';
import { I18n } from '@coze-arch/i18n';
import { ValueExpressionService } from '@/services';
import { nodeMetaValidate } from '@/nodes-v2/materials/node-meta-validate';
import {
fireNodeTitleChange,
provideNodeOutputVariablesEffect,
} from '@/node-registries/common/effects';
import { type FormData } from './types';
import { FormRender } from './form';
export const IMAGE_GENERATE_FORM_META: FormMetaV2<FormData> = {
// 节点表单渲染
render: () => <FormRender />,
// 验证触发时机
validateTrigger: ValidateTrigger.onChange,
// 验证规则
validate: {
nodeMeta: nodeMetaValidate,
['inputs.modelSetting.model']: ({ value, formValues }) => {
const invalidPreprocessors = {
1: [4, 5, 6],
8: [1, 2, 3, 4, 5, 6, 7],
3: [7],
6: [6, 7],
};
// 获取references字段
const references = formValues?.inputs?.references || [];
// 获取value对应的无效preprocessor值数组
const invalidValues = invalidPreprocessors[value] || [];
// 检查references中的preprocessor是否包含无效值
for (const reference of references) {
if (invalidValues.includes(reference?.preprocessor)) {
return I18n.t('Imageflow_not_support');
}
}
},
['inputs.prompt.prompt']: ({ value }) => {
if (!value) {
return I18n.t('workflow_detail_node_error_empty');
}
},
},
// 副作用管理
effect: {
nodeMeta: fireNodeTitleChange,
outputs: provideNodeOutputVariablesEffect,
},
// 默认值
defaultValues: () => ({
inputs: {
modelSetting: {
model: 1,
custom_ratio: {
width: 1024,
height: 1024,
},
ddim_steps: 25,
},
references: [],
prompt: {
prompt: '',
negative_prompt: '',
},
inputParameters: [],
},
outputs: [
{
key: nanoid(),
name: 'data',
type: ViewVariableType.Image,
},
{
key: nanoid(),
name: 'msg',
type: ViewVariableType.String,
},
],
}),
formatOnInit(value, context) {
const { node } = context;
const valueExpressionService = node.getService<ValueExpressionService>(
ValueExpressionService,
);
const references = get(value, 'inputs.references') || [];
set(
value,
'inputs.references',
references.map(item => ({
...item,
url: valueExpressionService.toVO(item.url),
})),
);
return value;
},
formatOnSubmit(value, context) {
const { node } = context;
const valueExpressionService = node.getService<ValueExpressionService>(
ValueExpressionService,
);
const references = get(value, 'inputs.references') || [];
set(
value,
'inputs.references',
references.map(item => ({
...item,
url: valueExpressionService.toDTO(item.url),
})),
);
return value;
},
};

View File

@@ -0,0 +1,71 @@
/*
* 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 { useUpdateEffect, usePrevious } from 'ahooks';
import { withNodeConfigForm } from '@/node-registries/common/hocs';
import {
OutputsField,
InputsParametersField,
} from '@/node-registries/common/fields';
import { useFieldValidate, useForm } from '@/form';
import { type FormData } from './types';
import { ModelSettingField, ReferencesField, PromptField } from './components';
export const FormRender = withNodeConfigForm(() => {
const validateModel = useFieldValidate('inputs.modelSetting.model');
useReferenceModelChangeEffect(validateModel);
return (
<>
<ModelSettingField name="inputs.modelSetting" />
<ReferencesField name="inputs.references" />
<InputsParametersField name="inputs.inputParameters" />
<PromptField name="inputs.prompt" />
<OutputsField name="outputs" readonly={true} />
</>
);
});
// 监听引用参考的模型变化触发模型设置的模型校验
// 用useWatch目前无法监听引用模型 先监听整个表单值
function useReferenceModelChangeEffect(callback: () => void) {
const form = useForm<FormData>();
const { values } = form;
const previousReferences = usePrevious(values?.inputs?.references);
useUpdateEffect(() => {
const currentPreprocessors = values?.inputs?.references?.map(
reference => reference.preprocessor,
);
const previousPreprocessors = previousReferences?.map(
reference => reference.preprocessor,
);
const isSamePreprocessors =
currentPreprocessors?.length === previousPreprocessors?.length &&
currentPreprocessors?.every(
(preprocessor, index) =>
preprocessor === previousPreprocessors?.[index],
);
if (!isSamePreprocessors) {
callback();
}
}, [values]);
}

View File

@@ -0,0 +1,17 @@
/*
* 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.
*/
export { IMAGE_GENERATE_NODE_REGISTRY } from './node-registry';

View File

@@ -0,0 +1,37 @@
/*
* 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 {
StandardNodeType,
type WorkflowNodeRegistry,
} from '@coze-workflow/base';
import { type NodeTestMeta } from '@/test-run-kit';
import { test } from './node-test';
import { IMAGE_GENERATE_FORM_META } from './form-meta';
export const IMAGE_GENERATE_NODE_REGISTRY: WorkflowNodeRegistry<NodeTestMeta> =
{
type: StandardNodeType.ImageGenerate,
width: 508,
meta: {
nodeDTOType: StandardNodeType.ImageGenerate,
test,
helpLink: '/open/docs/guides/image_generation_node',
},
formMeta: IMAGE_GENERATE_FORM_META,
};

View File

@@ -0,0 +1,49 @@
/*
* 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 { I18n, type I18nKeysNoOptionsType } from '@coze-arch/i18n';
import { FlowNodeFormData } from '@flowgram-adapter/free-layout-editor';
import { generateParametersToProperties } from '@/test-run-kit';
import { type NodeTestMeta } from '@/test-run-kit';
export const test: NodeTestMeta = {
generateFormInputProperties(node) {
const formData = node
.getData(FlowNodeFormData)
.formModel.getFormItemValueByPath('/');
const inputParameters =
formData?.inputParameters || formData?.inputs.inputParameters || [];
const references = (
formData?.references ||
formData?.inputs?.references ||
[]
)
.filter(item => item.preprocessor)
.map(item => ({
name: `__image_references_${item.preprocessor}`,
title: I18n.t(
`Imageflow_reference${item.preprocessor}` as I18nKeysNoOptionsType,
),
input: item.url,
}));
return {
...generateParametersToProperties(references, { node }),
...generateParametersToProperties(inputParameters, { node }),
};
},
};

View File

@@ -0,0 +1,51 @@
/*
* 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 ViewVariableType, type InputValueVO } from '@coze-workflow/base';
export interface FormData {
inputs: {
modelSetting: ModelSetting;
references: Reference[];
prompt: {
prompt: string;
negative_prompt: string;
};
inputParameters: InputValueVO[];
};
outputs: Output[] | (() => Output[]);
}
export interface ModelSetting {
model: number;
custom_ratio: {
width: number;
height: number;
};
ddim_steps: number;
}
export interface Reference {
preprocessor?: number;
url?: string;
weight?: number;
}
export interface Output {
key: string;
name: string;
type: ViewVariableType;
}