diff --git a/templates/metadata/pipeline/ai.yaml b/templates/metadata/pipeline/ai.yaml index 8b7959f6..3bd9b731 100644 --- a/templates/metadata/pipeline/ai.yaml +++ b/templates/metadata/pipeline/ai.yaml @@ -40,9 +40,8 @@ stages: label: en_US: Model zh_CN: 模型 - type: select + type: llm-model-selector required: true - scope: /provider/models/llm - name: max-round label: en_US: Max Round @@ -54,16 +53,8 @@ stages: label: en_US: Prompt zh_CN: 提示词 - type: array + type: prompt-editor required: true - items: - type: object - properties: - role: - type: string - default: user - content: - type: string - name: dify-service-api label: en_US: Dify Service API diff --git a/templates/metadata/pipeline/trigger.yaml b/templates/metadata/pipeline/trigger.yaml index 78759b11..ea7c596a 100644 --- a/templates/metadata/pipeline/trigger.yaml +++ b/templates/metadata/pipeline/trigger.yaml @@ -28,11 +28,9 @@ stages: description: en_US: The prefix of the message zh_CN: 消息前缀 - type: array + type: array[string] required: true default: [] - items: - type: string - name: regexp label: en_US: Regexp @@ -40,11 +38,9 @@ stages: description: en_US: The regexp of the message zh_CN: 消息正则表达式 - type: array + type: array[string] required: true default: [] - items: - type: string - name: random label: en_US: Random @@ -83,20 +79,16 @@ stages: label: en_US: Blacklist zh_CN: 黑名单 - type: array + type: array[string] required: true default: [] - items: - type: string - name: whitelist label: en_US: Whitelist zh_CN: 白名单 - type: array + type: array[string] required: true default: [] - items: - type: string - name: ignore-rules label: en_US: Ignore Rules @@ -109,11 +101,9 @@ stages: description: en_US: The prefix of the message zh_CN: 消息前缀 - type: array + type: array[string] required: true default: [] - items: - type: string - name: regexp label: en_US: Regexp @@ -121,8 +111,6 @@ stages: description: en_US: The regexp of the message zh_CN: 消息正则表达式 - type: array + type: array[string] required: true default: [] - items: - type: string diff --git a/web/package-lock.json b/web/package-lock.json index eb709ffe..a1ade004 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,6 +16,7 @@ "@radix-ui/react-select": "^2.2.4", "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-switch": "^1.2.4", + "@radix-ui/react-tabs": "^1.1.11", "@radix-ui/react-toggle": "^1.1.8", "@radix-ui/react-toggle-group": "^1.1.9", "@tailwindcss/postcss": "^4.1.5", @@ -1503,6 +1504,36 @@ } } }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.11.tgz", + "integrity": "sha512-4FiKSVoXqPP/KfzlB7lwwqoFV6EPwkrrqGp9cUYXjwDYHhvpnqq79P+EPHKcdoTE7Rl8w/+6s9rTlsfXHES9GA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.2", + "@radix-ui/react-roving-focus": "1.1.9", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toggle": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.8.tgz", diff --git a/web/package.json b/web/package.json index e800ae9b..2a1105bc 100644 --- a/web/package.json +++ b/web/package.json @@ -19,6 +19,7 @@ "@radix-ui/react-select": "^2.2.4", "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-switch": "^1.2.4", + "@radix-ui/react-tabs": "^1.1.11", "@radix-ui/react-toggle": "^1.1.8", "@radix-ui/react-toggle-group": "^1.1.9", "@tailwindcss/postcss": "^4.1.5", diff --git a/web/src/app/home/bots/components/bot-form/BotForm.tsx b/web/src/app/home/bots/components/bot-form/BotForm.tsx index 7a411fd6..d7332492 100644 --- a/web/src/app/home/bots/components/bot-form/BotForm.tsx +++ b/web/src/app/home/bots/components/bot-form/BotForm.tsx @@ -2,10 +2,10 @@ import { useEffect, useState } from 'react'; import { IChooseAdapterEntity, IPipelineEntity } from '@/app/home/bots/components/bot-form/ChooseEntity'; import { DynamicFormItemConfig, - IDynamicFormItemConfig, getDefaultValues, parseDynamicFormItemType, } from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; +import { IDynamicFormItemSchema } from '@/app/infra/entities/form/dynamic'; import { UUID } from 'uuidjs'; import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent'; import { httpClient } from '@/app/infra/http/HttpClient'; @@ -76,7 +76,7 @@ export default function BotForm({ const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false); const [adapterNameToDynamicConfigMap, setAdapterNameToDynamicConfigMap] = - useState(new Map()); + useState(new Map()); // const [form] = Form.useForm(); const [showDynamicForm, setShowDynamicForm] = useState(false); // const [dynamicForm] = Form.useForm(); @@ -95,7 +95,7 @@ export default function BotForm({ >([]); const [dynamicFormConfigList, setDynamicFormConfigList] = useState< - IDynamicFormItemConfig[] + IDynamicFormItemSchema[] >([]); const [isLoading, setIsLoading] = useState(false); diff --git a/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx b/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx index 77b527c5..e7ab9455 100644 --- a/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx +++ b/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx @@ -1,4 +1,4 @@ -import { IDynamicFormItemConfig } from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; +import { IDynamicFormItemSchema } from '@/app/infra/entities/form/dynamic'; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; @@ -18,7 +18,7 @@ export default function DynamicFormComponent({ onSubmit, initialValues, }: { - itemConfigList: IDynamicFormItemConfig[]; + itemConfigList: IDynamicFormItemSchema[]; onSubmit?: (val: object) => unknown; initialValues?: Record; }) { diff --git a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx index ffef6e7d..be745a2f 100644 --- a/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx +++ b/web/src/app/home/components/dynamic-form/DynamicFormItemComponent.tsx @@ -1,18 +1,18 @@ -// import { Form, Input, InputNumber, Select, Switch } from 'antd'; import { DynamicFormItemType, - IDynamicFormItemConfig, -} from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; + IDynamicFormItemSchema, +} from '@/app/infra/entities/form/dynamic'; import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select" import { Checkbox } from "@/components/ui/checkbox" import { ControllerRenderProps } from "react-hook-form"; +import { Button } from "@/components/ui/button"; export default function DynamicFormItemComponent({ config, field, }: { - config: IDynamicFormItemConfig; + config: IDynamicFormItemSchema; field: ControllerRenderProps; }) { switch (config.type) { @@ -39,21 +39,37 @@ export default function DynamicFormItemComponent({ case DynamicFormItemType.STRING_ARRAY: return ( - +
+ {field.value.map((item: string, index: number) => ( +
+ { + const newValue = [...field.value]; + newValue[index] = e.target.value; + field.onChange(newValue); + }} + /> + +
+ ))} + +
); case DynamicFormItemType.SELECT: @@ -67,9 +83,11 @@ export default function DynamicFormItemComponent({ - {/* 这里需要根据实际情况添加选项 */} - 选项1 - 选项2 + {config.options?.map((option) => ( + + {option.label.zh_CN} + + ))} diff --git a/web/src/app/home/components/dynamic-form/DynamicFormItemConfig.ts b/web/src/app/home/components/dynamic-form/DynamicFormItemConfig.ts index ce78622b..bb6db2a9 100644 --- a/web/src/app/home/components/dynamic-form/DynamicFormItemConfig.ts +++ b/web/src/app/home/components/dynamic-form/DynamicFormItemConfig.ts @@ -1,23 +1,17 @@ -export interface IDynamicFormItemConfig { - id: string; - default: string | number | boolean | Array; - label: IDynamicFormItemLabel; - name: string; - required: boolean; - type: DynamicFormItemType; - description?: IDynamicFormItemLabel; -} +import { IDynamicFormItemSchema, DynamicFormItemType, IDynamicFormItemOption } from '@/app/infra/entities/form/dynamic'; +import { I18nLabel } from '@/app/infra/entities/common'; -export class DynamicFormItemConfig implements IDynamicFormItemConfig { +export class DynamicFormItemConfig implements IDynamicFormItemSchema { id: string; name: string; default: string | number | boolean | Array; - label: IDynamicFormItemLabel; + label: I18nLabel; required: boolean; type: DynamicFormItemType; - description?: IDynamicFormItemLabel; + description?: I18nLabel; + options?: IDynamicFormItemOption[]; - constructor(params: IDynamicFormItemConfig) { + constructor(params: IDynamicFormItemSchema) { this.id = params.id; this.name = params.name; this.default = params.default; @@ -25,23 +19,10 @@ export class DynamicFormItemConfig implements IDynamicFormItemConfig { this.required = params.required; this.type = params.type; this.description = params.description; + this.options = params.options; } } -export interface IDynamicFormItemLabel { - en_US: string; - zh_CN: string; -} - -export enum DynamicFormItemType { - INT = 'integer', - FLOAT = 'float', - BOOLEAN = 'boolean', - STRING = 'string', - STRING_ARRAY = 'array[string]', - SELECT = 'select', - UNKNOWN = 'unknown', -} export function isDynamicFormItemType( value: string, @@ -55,7 +36,7 @@ export function parseDynamicFormItemType(value: string): DynamicFormItemType { return isDynamicFormItemType(value) ? value : DynamicFormItemType.UNKNOWN; } -export function getDefaultValues(itemConfigList: IDynamicFormItemConfig[]): Record { +export function getDefaultValues(itemConfigList: IDynamicFormItemSchema[]): Record { return itemConfigList.reduce((acc, item) => { acc[item.name] = item.default; return acc; diff --git a/web/src/app/home/components/dynamic-form/testDynamicConfigList.ts b/web/src/app/home/components/dynamic-form/testDynamicConfigList.ts index 244d7645..ca19b8b2 100644 --- a/web/src/app/home/components/dynamic-form/testDynamicConfigList.ts +++ b/web/src/app/home/components/dynamic-form/testDynamicConfigList.ts @@ -1,10 +1,10 @@ import { - DynamicFormItemConfig, DynamicFormItemType, - IDynamicFormItemConfig, -} from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; + IDynamicFormItemSchema, +} from '@/app/infra/entities/form/dynamic'; +import { DynamicFormItemConfig } from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; -export const testDynamicConfigList: IDynamicFormItemConfig[] = [ +export const testDynamicConfigList: IDynamicFormItemSchema[] = [ new DynamicFormItemConfig({ default: '', id: '111', diff --git a/web/src/app/home/models/component/llm-form/LLMForm.tsx b/web/src/app/home/models/component/llm-form/LLMForm.tsx index fe68a54f..1004a62f 100644 --- a/web/src/app/home/models/component/llm-form/LLMForm.tsx +++ b/web/src/app/home/models/component/llm-form/LLMForm.tsx @@ -3,7 +3,7 @@ import { ICreateLLMField } from '@/app/home/models/ICreateLLMField'; import { useEffect, useState } from 'react'; import { IChooseRequesterEntity } from '@/app/home/models/component/llm-form/ChooseRequesterEntity'; import { httpClient } from '@/app/infra/http/HttpClient'; -import { LLMModel } from '@/app/infra/api/api-types'; +import { LLMModel } from '@/app/infra/entities/api'; import { UUID } from 'uuidjs'; import { zodResolver } from "@hookform/resolvers/zod" @@ -178,7 +178,7 @@ export default function LLMForm({ const config = item.spec.config; for (let i = 0; i < config.length; i++) { if (config[i].name == 'base_url') { - return config[i].default; + return config[i].default?.toString() || ''; } } return ''; diff --git a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx index 2bcb54d1..ee3ab7eb 100644 --- a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx +++ b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormComponent.tsx @@ -1,19 +1,27 @@ -import { - Form, - Button, - Switch, - Select, - Input, - InputNumber, - SelectProps, -} from 'antd'; +// import { +// Form, +// Button, +// Switch, +// Select, +// Input, +// InputNumber, +// SelectProps, +// } from 'antd'; import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons'; import { useEffect, useState } from 'react'; import styles from './pipelineFormStyle.module.css'; import { httpClient } from '@/app/infra/http/HttpClient'; -import { LLMModel, Pipeline } from '@/app/infra/api/api-types'; +import { LLMModel, Pipeline } from '@/app/infra/entities/api'; import { UUID } from 'uuidjs'; -import { PipelineFormEntity } from '@/app/home/pipelines/components/pipeline-form/PipelineFormEntity'; +import { PipelineFormEntity, PipelineConfigTab, PipelineConfigStage } from '@/app/infra/entities/pipeline'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { + getDefaultValues, + parseDynamicFormItemType, +} from '@/app/home/components/dynamic-form/DynamicFormItemConfig'; +import { IDynamicFormItemSchema } from '@/app/infra/entities/form/dynamic'; +import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent'; +import { Button } from '@/components/ui/button'; export default function PipelineFormComponent({ initValues, @@ -31,48 +39,67 @@ export default function PipelineFormComponent({ }) { const [nowFormIndex, setNowFormIndex] = useState(0); const [nowAIRunner, setNowAIRunner] = useState(''); - const [llmModelList, setLlmModelList] = useState([]); + // const [llmModelList, setLlmModelList] = useState([]); // 这里不好,可以改成enum等 const formLabelList: FormLabel[] = [ - { label: '基础', name: 'basic' }, + { label: '基础信息', name: 'basic' }, { label: 'AI能力', name: 'ai' }, { label: '触发条件', name: 'trigger' }, { label: '安全能力', name: 'safety' }, { label: '输出处理', name: 'output' }, ]; - const [basicForm] = Form.useForm(); - const [aiForm] = Form.useForm(); - const [triggerForm] = Form.useForm(); - const [safetyForm] = Form.useForm(); - const [outputForm] = Form.useForm(); + // const [basicForm] = Form.useForm(); + // const [aiForm] = Form.useForm(); + // const [triggerForm] = Form.useForm(); + // const [safetyForm] = Form.useForm(); + // const [outputForm] = Form.useForm(); + const [aiConfigTabSchema, setAIConfigTabSchema] = useState(); + const [triggerConfigTabSchema, setTriggerConfigTabSchema] = useState(); + const [safetyConfigTabSchema, setSafetyConfigTabSchema] = useState(); + const [outputConfigTabSchema, setOutputConfigTabSchema] = useState(); useEffect(() => { getLLMModelList(); + + // get config schema from metadata + httpClient.getGeneralPipelineMetadata().then((resp) => { + for (const config of resp.configs) { + if (config.name === 'ai') { + setAIConfigTabSchema(config); + } else if (config.name === 'trigger') { + setTriggerConfigTabSchema(config); + } else if (config.name === 'safety') { + setSafetyConfigTabSchema(config); + } else if (config.name === 'output') { + setOutputConfigTabSchema(config); + } + } + }); }, []); - useEffect(() => { - console.log('initValues change: ', initValues); - if (initValues) { - basicForm.setFieldsValue(initValues.basic); - aiForm.setFieldsValue(initValues.ai); - triggerForm.setFieldsValue(initValues.trigger); - safetyForm.setFieldsValue(initValues.safety); - outputForm.setFieldsValue(initValues.output); - } - }, [aiForm, basicForm, initValues, outputForm, safetyForm, triggerForm]); + // useEffect(() => { + // console.log('initValues change: ', initValues); + // if (initValues) { + // // basicForm.setFieldsValue(initValues.basic); + // // aiForm.setFieldsValue(initValues.ai); + // // triggerForm.setFieldsValue(initValues.trigger); + // // safetyForm.setFieldsValue(initValues.safety); + // // outputForm.setFieldsValue(initValues.output); + // } + // }, [aiForm, basicForm, initValues, outputForm, safetyForm, triggerForm]); function getLLMModelList() { httpClient .getProviderLLMModels() .then((resp) => { - setLlmModelList( - resp.models.map((model: LLMModel) => { - return { - value: model.uuid, - label: model.name, - }; - }), - ); + // setLlmModelList( + // resp.models.map((model: LLMModel) => { + // return { + // value: model.uuid, + // label: model.name, + // }; + // }), + // ); }) .catch((err) => { console.error('get LLM model list error', err); @@ -120,511 +147,89 @@ export default function PipelineFormComponent({ } function handleCreate() { - Promise.all([ - basicForm.validateFields(), - aiForm.validateFields(), - triggerForm.validateFields(), - safetyForm.validateFields(), - outputForm.validateFields(), - ]) - .then(() => { - const pipeline = assembleForm(); - httpClient.createPipeline(pipeline).then(() => onFinish()); - }) - .catch((e) => { - console.error(e); - }); + // Promise.all([ + // // basicForm.validateFields(), + // // aiForm.validateFields(), + // // triggerForm.validateFields(), + // // safetyForm.validateFields(), + // // outputForm.validateFields(), + // ]) + // .then(() => { + // const pipeline = assembleForm(); + // httpClient.createPipeline(pipeline).then(() => onFinish()); + // }) + // .catch((e) => { + // console.error(e); + // }); } function handleModify() { - Promise.all([ - basicForm.validateFields(), - aiForm.validateFields(), - triggerForm.validateFields(), - safetyForm.validateFields(), - outputForm.validateFields(), - ]) - .then(() => { - const pipeline = assembleForm(); - httpClient - .updatePipeline(pipelineId || '', pipeline) - .then(() => onFinish()); - }) - .catch((e) => { - console.error(e); - }); + // Promise.all([ + // // basicForm.validateFields(), + // // aiForm.validateFields(), + // // triggerForm.validateFields(), + // // safetyForm.validateFields(), + // // outputForm.validateFields(), + // ]) + // .then(() => { + // const pipeline = assembleForm(); + // httpClient + // .updatePipeline(pipelineId || '', pipeline) + // .then(() => onFinish()); + // }) + // .catch((e) => { + // console.error(e); + // }); } // TODO 类型混乱,需要优化 - function assembleForm(): Pipeline { - console.log('basicForm:', basicForm.getFieldsValue()); - console.log('aiForm:', aiForm.getFieldsValue()); - console.log('triggerForm:', triggerForm.getFieldsValue()); - console.log('safetyForm:', safetyForm.getFieldsValue()); - console.log('outputForm:', outputForm.getFieldsValue()); - const config: object = { - ai: aiForm.getFieldsValue(), - trigger: triggerForm.getFieldsValue(), - safety: safetyForm.getFieldsValue(), - output: outputForm.getFieldsValue(), - }; + // function assembleForm(): Pipeline { + // console.log('basicForm:', basicForm.getFieldsValue()); + // console.log('aiForm:', aiForm.getFieldsValue()); + // console.log('triggerForm:', triggerForm.getFieldsValue()); + // console.log('safetyForm:', safetyForm.getFieldsValue()); + // console.log('outputForm:', outputForm.getFieldsValue()); + // const config: object = { + // ai: aiForm.getFieldsValue(), + // trigger: triggerForm.getFieldsValue(), + // safety: safetyForm.getFieldsValue(), + // output: outputForm.getFieldsValue(), + // }; - return { - config, - created_at: '', - description: basicForm.getFieldsValue().description, - for_version: '', - name: basicForm.getFieldsValue().name, - stages: [], - updated_at: '', - uuid: UUID.generate(), - }; - } + // return { + // config, + // created_at: '', + // description: basicForm.getFieldsValue().description, + // for_version: '', + // name: basicForm.getFieldsValue().name, + // stages: [], + // updated_at: '', + // uuid: UUID.generate(), + // }; + // } return (
-

{getNowFormLabel().label}

-
- - - - - - -
- {/* AI能力表单 ai */} -
- {/* Runner 配置区块 */} -
运行器
- - - - - - - {/* TODO 这里要做转换处理 */} - - - - - )} - {/* Dify 服务 API 区块 */} - {nowAIRunner === 'dify-service-api' && ( - <> -
配置Dify服务API
- - - - - ...\<\/think\>', value: 'plain' }, - { label: '原始', value: 'original' }, - { label: '移除', value: 'remove' }, - ]} - /> - - - )} - {/* 阿里云百炼区块 */} - {nowAIRunner === 'dashscope-app-api' && ( - <> -
- 配置阿里云百炼平台 API -
- - - - - - - - )} -
- {/* 触发条件表单 trigger */} -
- {/* 群响应规则块 */} -
群响应规则
- - - - - - - - - -
访问控制
- - - - - - - - - - - - - - - - - {/* 速率限制块 rate-limit */} -
速率限制
- - - - - - - - - - - - - - {/* 强制延迟区块 */} -
强制延迟
- - - - - - - - {/* 杂项区块 */} -
杂项
- - - - - - - - - - - - -
- -
+ {/*
-
+
*/}
); } diff --git a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormEntity.ts b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormEntity.ts index 142e7898..e69de29b 100644 --- a/web/src/app/home/pipelines/components/pipeline-form/PipelineFormEntity.ts +++ b/web/src/app/home/pipelines/components/pipeline-form/PipelineFormEntity.ts @@ -1,7 +0,0 @@ -export interface PipelineFormEntity { - basic: object; - ai: object; - trigger: object; - safety: object; - output: object; -} diff --git a/web/src/app/home/pipelines/page.tsx b/web/src/app/home/pipelines/page.tsx index e908530a..f7ab0483 100644 --- a/web/src/app/home/pipelines/page.tsx +++ b/web/src/app/home/pipelines/page.tsx @@ -1,5 +1,4 @@ 'use client'; -import { Modal } from 'antd'; import { useState, useEffect } from 'react'; import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent'; import PipelineFormComponent from './components/pipeline-form/PipelineFormComponent'; @@ -8,6 +7,14 @@ import { PipelineCardVO } from '@/app/home/pipelines/components/pipeline-card/Pi import PipelineCard from '@/app/home/pipelines/components/pipeline-card/PipelineCard'; import { PipelineFormEntity } from '@/app/home/pipelines/components/pipeline-form/PipelineFormEntity'; import styles from './pipelineConfig.module.css'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" import { Button } from '@/components/ui/button'; export default function PluginConfigPage() { @@ -74,7 +81,7 @@ export default function PluginConfigPage() { return (
- - + */} + + + + + {isEditForm ? '编辑流水线' : '创建流水线'} + + + { + getPipelines(); + setModalOpen(false); + }} + isEditMode={isEditForm} + pipelineId={selectedPipelineId} + disableForm={disableForm} + initValues={selectedPipelineFormValue} + /> + + + {pipelineList.length > 0 && (
diff --git a/web/src/app/infra/api/api-types/index.ts b/web/src/app/infra/entities/api/index.ts similarity index 94% rename from web/src/app/infra/api/api-types/index.ts rename to web/src/app/infra/entities/api/index.ts index b4c2f1a6..eb92f6a1 100644 --- a/web/src/app/infra/api/api-types/index.ts +++ b/web/src/app/infra/entities/api/index.ts @@ -1,3 +1,7 @@ +import { IDynamicFormItemSchema } from '@/app/infra/entities/form/dynamic'; +import { I18nLabel } from '@/app/infra/entities/common'; +import { PipelineConfigTab } from '@/app/infra/entities/pipeline'; + export interface ApiResponse { code: number; data: T; @@ -26,7 +30,9 @@ export interface Requester { label: I18nText; description: I18nText; icon?: string; - spec: object; + spec: { + config: IDynamicFormItemSchema[]; + } } export interface ApiRespProviderLLMModels { @@ -302,3 +308,7 @@ interface GetPipeline { export interface GetPipelineResponseData { pipeline: GetPipeline; } + +export interface GetPipelineMetadataResponseData { + configs: PipelineConfigTab[]; +} \ No newline at end of file diff --git a/web/src/app/infra/entities/common.ts b/web/src/app/infra/entities/common.ts new file mode 100644 index 00000000..3408c105 --- /dev/null +++ b/web/src/app/infra/entities/common.ts @@ -0,0 +1,5 @@ +export interface I18nLabel { + en_US: string; + zh_CN: string; + ja_JP?: string; +} diff --git a/web/src/app/infra/entities/form/dynamic.ts b/web/src/app/infra/entities/form/dynamic.ts new file mode 100644 index 00000000..6e70062b --- /dev/null +++ b/web/src/app/infra/entities/form/dynamic.ts @@ -0,0 +1,29 @@ +import { I18nLabel } from '@/app/infra/entities/common'; + +export interface IDynamicFormItemSchema { + id: string; + default: string | number | boolean | Array; + label: I18nLabel; + name: string; + required: boolean; + type: DynamicFormItemType; + description?: I18nLabel; + options?: IDynamicFormItemOption[]; + } + +export enum DynamicFormItemType { + INT = 'integer', + FLOAT = 'float', + BOOLEAN = 'boolean', + STRING = 'string', + STRING_ARRAY = 'array[string]', + SELECT = 'select', + LLM_MODEL_SELECTOR = 'llm-model-selector', + PROMPT_EDITOR = 'prompt-editor', + UNKNOWN = 'unknown', + } + +export interface IDynamicFormItemOption { + name: string; + label: I18nLabel; + } \ No newline at end of file diff --git a/web/src/app/infra/entities/pipeline/index.ts b/web/src/app/infra/entities/pipeline/index.ts new file mode 100644 index 00000000..6bd79ccb --- /dev/null +++ b/web/src/app/infra/entities/pipeline/index.ts @@ -0,0 +1,22 @@ +import { I18nLabel } from '@/app/infra/entities/common'; +import { IDynamicFormItemSchema } from '@/app/infra/entities/form/dynamic'; + +export interface PipelineFormEntity { + basic: object; + ai: object; + trigger: object; + safety: object; + output: object; +} + +export interface PipelineConfigTab { + name: string; + label: I18nLabel; + stages: PipelineConfigStage[]; +} + +export interface PipelineConfigStage { + name: string; + label: I18nLabel; + config: IDynamicFormItemSchema[]; +} \ No newline at end of file diff --git a/web/src/app/infra/http/HttpClient.ts b/web/src/app/infra/http/HttpClient.ts index 325627af..cf1f1546 100644 --- a/web/src/app/infra/http/HttpClient.ts +++ b/web/src/app/infra/http/HttpClient.ts @@ -28,7 +28,8 @@ import { ApiRespUserToken, MarketPluginResponse, GetPipelineResponseData, -} from '../api/api-types'; + GetPipelineMetadataResponseData +} from '@/app/infra/entities/api'; import { notification } from 'antd'; type JSONValue = string | number | boolean | JSONObject | JSONArray | null; @@ -249,7 +250,7 @@ class HttpClient { } // ============ Pipeline API ============ - public getGeneralPipelineMetadata(): Promise { + public getGeneralPipelineMetadata(): Promise { // as designed, this method will be deprecated, and only for developer to check the prefered config schema return this.get('/api/v1/pipelines/_/metadata'); } diff --git a/web/src/components/ui/tabs.tsx b/web/src/components/ui/tabs.tsx new file mode 100644 index 00000000..497ba5ea --- /dev/null +++ b/web/src/components/ui/tabs.tsx @@ -0,0 +1,66 @@ +"use client" + +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +function Tabs({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function TabsList({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function TabsTrigger({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function TabsContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Tabs, TabsList, TabsTrigger, TabsContent }