jiaxing.liao недель назад: 2
Родитель
Сommit
7825c33984
35 измененных файлов с 1514 добавлено и 619 удалено
  1. 0 30
      apps/web/components.d.ts
  2. 1 0
      apps/web/package.json
  3. 118 92
      apps/web/src/components/SetterCommon/condition/ConditionBuilder.vue
  4. 0 1
      apps/web/src/components/Sidebar/index.vue
  5. 1 1
      apps/web/src/features/createModal/index.vue
  6. 6 12
      apps/web/src/features/nodeLibary/index.vue
  7. 0 0
      apps/web/src/features/setter/CodeSetter.vue
  8. 0 0
      apps/web/src/features/setter/ConditionSetter.vue
  9. 0 0
      apps/web/src/features/setter/DatabaseSetter.vue
  10. 0 0
      apps/web/src/features/setter/HttpSetter.vue
  11. 0 0
      apps/web/src/features/setter/index.vue
  12. 1 1
      apps/web/src/features/toolbar/index.vue
  13. 2 0
      apps/web/src/types/nprogress.d.ts
  14. 2 2
      apps/web/src/views/Chat.vue
  15. 58 54
      apps/web/src/views/Editor.vue
  16. 473 84
      packages/api-service/agent.openapi.json
  17. 247 175
      packages/api-service/servers/api/agent.ts
  18. 3 3
      packages/api-service/servers/api/index.ts
  19. 171 0
      packages/nodes/Interface.ts
  20. 1 2
      packages/nodes/index.ts
  21. 12 5
      packages/nodes/materials/code.tsx
  22. 17 2
      packages/nodes/materials/condition.ts
  23. 3 1
      packages/nodes/materials/end.ts
  24. 17 32
      packages/nodes/materials/http.ts
  25. 49 2
      packages/nodes/materials/iteration.ts
  26. 57 2
      packages/nodes/materials/list.ts
  27. 55 2
      packages/nodes/materials/loop.ts
  28. 0 17
      packages/nodes/nodes/chat/chat.node.ts
  29. 0 18
      packages/nodes/nodes/if/if.node.ts
  30. 2 1
      packages/workflow/index.ts
  31. 12 10
      packages/workflow/src/components/Canvas.vue
  32. 1 3
      packages/workflow/src/components/elements/control-bar/CanvasControlBar.vue
  33. 8 4
      packages/workflow/src/components/elements/nodes/CanvasNode.vue
  34. 98 0
      packages/workflow/src/hooks/useDragAndDrop.ts
  35. 99 63
      pnpm-lock.yaml

+ 0 - 30
apps/web/components.d.ts

@@ -17,7 +17,6 @@ declare module 'vue' {
     CodeSetter: typeof import('./src/components/setter/CodeSetter.vue')['default']
     CodeSetter: typeof import('./src/components/setter/CodeSetter.vue')['default']
     ConditionBuilder: typeof import('./src/components/SetterCommon/condition/ConditionBuilder.vue')['default']
     ConditionBuilder: typeof import('./src/components/SetterCommon/condition/ConditionBuilder.vue')['default']
     ConditionSetter: typeof import('./src/components/setter/ConditionSetter.vue')['default']
     ConditionSetter: typeof import('./src/components/setter/ConditionSetter.vue')['default']
-    CustomDropdown: typeof import('./src/components/CustomDropdown/index.vue')['default']
     DatabaseSetter: typeof import('./src/components/setter/DatabaseSetter.vue')['default']
     DatabaseSetter: typeof import('./src/components/setter/DatabaseSetter.vue')['default']
     ElAside: typeof import('element-plus/es')['ElAside']
     ElAside: typeof import('element-plus/es')['ElAside']
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
@@ -31,16 +30,12 @@ declare module 'vue' {
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDivider: typeof import('element-plus/es')['ElDivider']
-    ElDorpdown: typeof import('element-plus/es')['ElDorpdown']
-    ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
     ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
     ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
     ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
     ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
     ElEmpty: typeof import('element-plus/es')['ElEmpty']
     ElEmpty: typeof import('element-plus/es')['ElEmpty']
-    ElFooter: typeof import('element-plus/es')['ElFooter']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElHeader: typeof import('element-plus/es')['ElHeader']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
@@ -56,40 +51,30 @@ declare module 'vue' {
     ElRow: typeof import('element-plus/es')['ElRow']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSplitter: typeof import('element-plus/es')['ElSplitter']
     ElSplitter: typeof import('element-plus/es')['ElSplitter']
     ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
     ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
-    ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
-    ElTab: typeof import('element-plus/es')['ElTab']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
-    ElTooltop: typeof import('element-plus/es')['ElTooltop']
     ErrorHandling: typeof import('./src/components/SetterCommon/Code/ErrorHandling.vue')['default']
     ErrorHandling: typeof import('./src/components/SetterCommon/Code/ErrorHandling.vue')['default']
     ExecutionChart: typeof import('./src/components/Chart/ExecutionChart.vue')['default']
     ExecutionChart: typeof import('./src/components/Chart/ExecutionChart.vue')['default']
     HttpSetter: typeof import('./src/components/setter/HttpSetter.vue')['default']
     HttpSetter: typeof import('./src/components/setter/HttpSetter.vue')['default']
     InputVariables: typeof import('./src/components/SetterCommon/Code/InputVariables.vue')['default']
     InputVariables: typeof import('./src/components/SetterCommon/Code/InputVariables.vue')['default']
-    NodeToolBar: typeof import('../../packages/workflow/src/components/elements/node-tool-bar/index.vue')['default']
-    NodeTools: typeof import('./src/components/NodeTools/index.vue')['default']
     OutputVariables: typeof import('./src/components/SetterCommon/Code/OutputVariables.vue')['default']
     OutputVariables: typeof import('./src/components/SetterCommon/Code/OutputVariables.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     RouterView: typeof import('vue-router')['RouterView']
-    RunWork: typeof import('./src/components/RunWorkflow/RunWork.vue')['default']
     RunWorkflow: typeof import('./src/components/RunWorkflow/index.vue')['default']
     RunWorkflow: typeof import('./src/components/RunWorkflow/index.vue')['default']
     SearchDialog: typeof import('./src/components/SearchDialog/index.vue')['default']
     SearchDialog: typeof import('./src/components/SearchDialog/index.vue')['default']
     Setter: typeof import('./src/components/setter/index.vue')['default']
     Setter: typeof import('./src/components/setter/index.vue')['default']
     Sidebar: typeof import('./src/components/Sidebar/index.vue')['default']
     Sidebar: typeof import('./src/components/Sidebar/index.vue')['default']
     SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
     SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
-    TabGroup: typeof import('./src/components/SetterCommon/Code/TabGroup.vue')['default']
     TemplateModal: typeof import('./src/components/TemplateModal/index.vue')['default']
     TemplateModal: typeof import('./src/components/TemplateModal/index.vue')['default']
     TestConfig: typeof import('./src/components/SetterCommon/Code/TestConfig.vue')['default']
     TestConfig: typeof import('./src/components/SetterCommon/Code/TestConfig.vue')['default']
-    VariablePicker: typeof import('./src/components/SetterCommon/condition/VariablePicker.vue')['default']
   }
   }
   export interface GlobalDirectives {
   export interface GlobalDirectives {
     vLoading: typeof import('element-plus/es')['ElLoadingDirective']
     vLoading: typeof import('element-plus/es')['ElLoadingDirective']
@@ -103,7 +88,6 @@ declare global {
   const CodeSetter: typeof import('./src/components/setter/CodeSetter.vue')['default']
   const CodeSetter: typeof import('./src/components/setter/CodeSetter.vue')['default']
   const ConditionBuilder: typeof import('./src/components/SetterCommon/condition/ConditionBuilder.vue')['default']
   const ConditionBuilder: typeof import('./src/components/SetterCommon/condition/ConditionBuilder.vue')['default']
   const ConditionSetter: typeof import('./src/components/setter/ConditionSetter.vue')['default']
   const ConditionSetter: typeof import('./src/components/setter/ConditionSetter.vue')['default']
-  const CustomDropdown: typeof import('./src/components/CustomDropdown/index.vue')['default']
   const DatabaseSetter: typeof import('./src/components/setter/DatabaseSetter.vue')['default']
   const DatabaseSetter: typeof import('./src/components/setter/DatabaseSetter.vue')['default']
   const ElAside: typeof import('element-plus/es')['ElAside']
   const ElAside: typeof import('element-plus/es')['ElAside']
   const ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
   const ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
@@ -117,16 +101,12 @@ declare global {
   const ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
   const ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
   const ElDialog: typeof import('element-plus/es')['ElDialog']
   const ElDialog: typeof import('element-plus/es')['ElDialog']
   const ElDivider: typeof import('element-plus/es')['ElDivider']
   const ElDivider: typeof import('element-plus/es')['ElDivider']
-  const ElDorpdown: typeof import('element-plus/es')['ElDorpdown']
-  const ElDrawer: typeof import('element-plus/es')['ElDrawer']
   const ElDropdown: typeof import('element-plus/es')['ElDropdown']
   const ElDropdown: typeof import('element-plus/es')['ElDropdown']
   const ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
   const ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
   const ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
   const ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
   const ElEmpty: typeof import('element-plus/es')['ElEmpty']
   const ElEmpty: typeof import('element-plus/es')['ElEmpty']
-  const ElFooter: typeof import('element-plus/es')['ElFooter']
   const ElForm: typeof import('element-plus/es')['ElForm']
   const ElForm: typeof import('element-plus/es')['ElForm']
   const ElFormItem: typeof import('element-plus/es')['ElFormItem']
   const ElFormItem: typeof import('element-plus/es')['ElFormItem']
-  const ElHeader: typeof import('element-plus/es')['ElHeader']
   const ElIcon: typeof import('element-plus/es')['ElIcon']
   const ElIcon: typeof import('element-plus/es')['ElIcon']
   const ElInput: typeof import('element-plus/es')['ElInput']
   const ElInput: typeof import('element-plus/es')['ElInput']
   const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
   const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
@@ -142,38 +122,28 @@ declare global {
   const ElRow: typeof import('element-plus/es')['ElRow']
   const ElRow: typeof import('element-plus/es')['ElRow']
   const ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
   const ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
   const ElSelect: typeof import('element-plus/es')['ElSelect']
   const ElSelect: typeof import('element-plus/es')['ElSelect']
-  const ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-  const ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
   const ElSlider: typeof import('element-plus/es')['ElSlider']
   const ElSlider: typeof import('element-plus/es')['ElSlider']
   const ElSplitter: typeof import('element-plus/es')['ElSplitter']
   const ElSplitter: typeof import('element-plus/es')['ElSplitter']
   const ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
   const ElSplitterPanel: typeof import('element-plus/es')['ElSplitterPanel']
-  const ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
   const ElSwitch: typeof import('element-plus/es')['ElSwitch']
   const ElSwitch: typeof import('element-plus/es')['ElSwitch']
-  const ElTab: typeof import('element-plus/es')['ElTab']
   const ElTable: typeof import('element-plus/es')['ElTable']
   const ElTable: typeof import('element-plus/es')['ElTable']
   const ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
   const ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
   const ElTabPane: typeof import('element-plus/es')['ElTabPane']
   const ElTabPane: typeof import('element-plus/es')['ElTabPane']
   const ElTabs: typeof import('element-plus/es')['ElTabs']
   const ElTabs: typeof import('element-plus/es')['ElTabs']
   const ElTag: typeof import('element-plus/es')['ElTag']
   const ElTag: typeof import('element-plus/es')['ElTag']
   const ElTooltip: typeof import('element-plus/es')['ElTooltip']
   const ElTooltip: typeof import('element-plus/es')['ElTooltip']
-  const ElTooltop: typeof import('element-plus/es')['ElTooltop']
   const ErrorHandling: typeof import('./src/components/SetterCommon/Code/ErrorHandling.vue')['default']
   const ErrorHandling: typeof import('./src/components/SetterCommon/Code/ErrorHandling.vue')['default']
   const ExecutionChart: typeof import('./src/components/Chart/ExecutionChart.vue')['default']
   const ExecutionChart: typeof import('./src/components/Chart/ExecutionChart.vue')['default']
   const HttpSetter: typeof import('./src/components/setter/HttpSetter.vue')['default']
   const HttpSetter: typeof import('./src/components/setter/HttpSetter.vue')['default']
   const InputVariables: typeof import('./src/components/SetterCommon/Code/InputVariables.vue')['default']
   const InputVariables: typeof import('./src/components/SetterCommon/Code/InputVariables.vue')['default']
-  const NodeToolBar: typeof import('../../packages/workflow/src/components/elements/node-tool-bar/index.vue')['default']
-  const NodeTools: typeof import('./src/components/NodeTools/index.vue')['default']
   const OutputVariables: typeof import('./src/components/SetterCommon/Code/OutputVariables.vue')['default']
   const OutputVariables: typeof import('./src/components/SetterCommon/Code/OutputVariables.vue')['default']
   const RouterLink: typeof import('vue-router')['RouterLink']
   const RouterLink: typeof import('vue-router')['RouterLink']
   const RouterView: typeof import('vue-router')['RouterView']
   const RouterView: typeof import('vue-router')['RouterView']
-  const RunWork: typeof import('./src/components/RunWorkflow/RunWork.vue')['default']
   const RunWorkflow: typeof import('./src/components/RunWorkflow/index.vue')['default']
   const RunWorkflow: typeof import('./src/components/RunWorkflow/index.vue')['default']
   const SearchDialog: typeof import('./src/components/SearchDialog/index.vue')['default']
   const SearchDialog: typeof import('./src/components/SearchDialog/index.vue')['default']
   const Setter: typeof import('./src/components/setter/index.vue')['default']
   const Setter: typeof import('./src/components/setter/index.vue')['default']
   const Sidebar: typeof import('./src/components/Sidebar/index.vue')['default']
   const Sidebar: typeof import('./src/components/Sidebar/index.vue')['default']
   const SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
   const SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
-  const TabGroup: typeof import('./src/components/SetterCommon/Code/TabGroup.vue')['default']
   const TemplateModal: typeof import('./src/components/TemplateModal/index.vue')['default']
   const TemplateModal: typeof import('./src/components/TemplateModal/index.vue')['default']
   const TestConfig: typeof import('./src/components/SetterCommon/Code/TestConfig.vue')['default']
   const TestConfig: typeof import('./src/components/SetterCommon/Code/TestConfig.vue')['default']
-  const VariablePicker: typeof import('./src/components/SetterCommon/condition/VariablePicker.vue')['default']
 }
 }

+ 1 - 0
apps/web/package.json

@@ -32,6 +32,7 @@
     "@repo/ui": "workspace:*",
     "@repo/ui": "workspace:*",
     "@repo/workflow": "workspace:*",
     "@repo/workflow": "workspace:*",
     "@types/lodash-es": "^4.17.12",
     "@types/lodash-es": "^4.17.12",
+    "@types/nprogress": "^0.2.3",
     "@vitejs/plugin-vue": "^6.0.1",
     "@vitejs/plugin-vue": "^6.0.1",
     "@vue/tsconfig": "^0.8.1",
     "@vue/tsconfig": "^0.8.1",
     "esbuild": "^0.27.2",
     "esbuild": "^0.27.2",

+ 118 - 92
apps/web/src/components/SetterCommon/condition/ConditionBuilder.vue

@@ -1,135 +1,161 @@
 <template>
 <template>
-    <div class="space-y-2">
-        <!-- 条件行 -->
-        <div v-for="(condition, index) in conditions" :key="condition.id" class="flex items-center gap-1">
-            <!-- 左侧变量选择 -->
-            <ElSelect placeholder="选择变量" class="w-1/4" v-model="condition.leftValue" @change="handleConditionChange">
-                <ElOption v-for="variable in availableVariables" :key="variable.id" :value="variable.name"
-                    :label="variable.name + `  (${variable.type})`" />
-            </ElSelect>
-
-            <!-- 右侧值输入 -->
-            <ElInput v-model="condition.rightValue" type="text" placeholder="输入值" @input="handleConditionChange"
-                class="w-1/4 text-sm bg-white" />
-
-            <!-- 运算符选择 -->
-            <ElSelect placeholder="选择条件" v-model="condition.operator" @change="handleConditionChange"
-                class="w-1/4 text-sm bg-white">
-                <ElOption v-for="li in operators" :key="li.value" :value="li.value" :label="li.label" />
-            </ElSelect>
-
-            <!-- 删除按钮 -->
-            <ElButton v-if="conditions.length > 1" @click="removeCondition(index)"
-                class="p-2 w-1/4 opacity-50 hover:opacity-100 hover:bg-red-50 rounded transition-all" title="删除条件">
-                <Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
-            </ElButton>
-        </div>
-
-        <!-- 添加条件按钮 -->
-        <div class="text-right" v-if="conditions[0]?.id !== 'else'">
-            <ElButton @click="addCondition"
-                class="flex items-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
-                <Icon icon="lucide:git-branch-plus" :height="16" :width="16" />
-                添加条件
-            </ElButton>
-        </div>
-
-    </div>
+	<div class="space-y-2">
+		<!-- 条件行 -->
+		<div
+			v-for="(condition, index) in conditions"
+			:key="condition.id"
+			class="flex items-center gap-1"
+		>
+			<!-- 左侧变量选择 -->
+			<ElSelect
+				placeholder="选择变量"
+				class="w-1/4"
+				v-model="condition.leftValue"
+				@change="handleConditionChange"
+			>
+				<ElOption
+					v-for="variable in availableVariables"
+					:key="variable.id"
+					:value="variable.name"
+					:label="variable.name + `  (${variable.type})`"
+				/>
+			</ElSelect>
+
+			<!-- 右侧值输入 -->
+			<ElInput
+				v-model="condition.rightValue"
+				type="text"
+				placeholder="输入值"
+				@input="handleConditionChange"
+				class="w-1/4 text-sm bg-white"
+			/>
+
+			<!-- 运算符选择 -->
+			<ElSelect
+				placeholder="选择条件"
+				v-model="condition.operator"
+				@change="handleConditionChange"
+				class="w-1/4 text-sm bg-white"
+			>
+				<ElOption v-for="li in operators" :key="li.value" :value="li.value" :label="li.label" />
+			</ElSelect>
+
+			<!-- 删除按钮 -->
+			<ElButton
+				v-if="conditions.length > 1"
+				@click="removeCondition(index)"
+				class="p-2 w-1/4 opacity-50 hover:opacity-100 hover:bg-red-50 rounded transition-all"
+				title="删除条件"
+			>
+				<Icon icon="lucide:trash-2" :height="16" :width="16" class="text-red-500" />
+			</ElButton>
+		</div>
+
+		<!-- 添加条件按钮 -->
+		<div class="text-right" v-if="conditions[0]?.id !== 'else'">
+			<ElButton
+				@click="addCondition"
+				class="flex items-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
+			>
+				<Icon icon="lucide:git-branch-plus" :height="16" :width="16" />
+				添加条件
+			</ElButton>
+		</div>
+	</div>
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { ref, computed, watch } from 'vue'
+import { ref, watch } from 'vue'
 import { Icon } from '@iconify/vue'
 import { Icon } from '@iconify/vue'
 
 
 interface Condition {
 interface Condition {
-    id: string
-    leftValue: string
-    operator: string
-    rightValue: string
+	id: string
+	leftValue: string
+	operator: string
+	rightValue: string
 }
 }
 
 
 interface Props {
 interface Props {
-    modelValue: Condition[]
+	modelValue: Condition[]
 }
 }
 
 
 interface Emits {
 interface Emits {
-    (e: 'update:modelValue', value: Condition[]): void
-    (e: 'openVariablePicker', index: number, side: 'left' | 'right'): void
+	(e: 'update:modelValue', value: Condition[]): void
+	(e: 'openVariablePicker', index: number, side: 'left' | 'right'): void
 }
 }
 interface Variable {
 interface Variable {
-    id: string
-    name: string
-    type: string
-    source: string
+	id: string
+	name: string
+	type: string
+	source: string
 }
 }
 // 可用变量列表
 // 可用变量列表
 const availableVariables: Variable[] = [
 const availableVariables: Variable[] = [
-    { id: 'var_1', name: 'sys.user_id', type: 'String', source: 'HTTP 请求' },
-    { id: 'var_2', name: 'sys.app_id', type: 'Number', source: 'HTTP 请求' },
-    { id: 'var_3', name: 'result', type: 'String', source: '代码执行' },
-    { id: 'var_4', name: 'output_format', type: 'String', source: 'SQL查询' },
-    { id: 'var_5', name: 'user_name', type: 'String', source: 'HTTP 请求' },
-    { id: 'var_6', name: 'user_email', type: 'String', source: 'HTTP 请求' },
+	{ id: 'var_1', name: 'sys.user_id', type: 'String', source: 'HTTP 请求' },
+	{ id: 'var_2', name: 'sys.app_id', type: 'Number', source: 'HTTP 请求' },
+	{ id: 'var_3', name: 'result', type: 'String', source: '代码执行' },
+	{ id: 'var_4', name: 'output_format', type: 'String', source: 'SQL查询' },
+	{ id: 'var_5', name: 'user_name', type: 'String', source: 'HTTP 请求' },
+	{ id: 'var_6', name: 'user_email', type: 'String', source: 'HTTP 请求' }
 ]
 ]
 
 
 interface OperatorsType {
 interface OperatorsType {
-    value: string
-    label: string
+	value: string
+	label: string
 }
 }
 // 运算符列表
 // 运算符列表
 const operators: OperatorsType[] = [
 const operators: OperatorsType[] = [
-    { value: 'equals', label: '等于' },
-    { value: 'notEquals', label: '不等于' },
-    { value: 'contains', label: '包含' },
-    { value: 'notContains', label: '不包含' },
-    { value: 'greaterThan', label: '大于' },
-    { value: 'lessThan', label: '小于' },
-    { value: 'greaterOrEqual', label: '大于等于' },
-    { value: 'lessOrEqual', label: '小于等于' }
+	{ value: 'equals', label: '等于' },
+	{ value: 'notEquals', label: '不等于' },
+	{ value: 'contains', label: '包含' },
+	{ value: 'notContains', label: '不包含' },
+	{ value: 'greaterThan', label: '大于' },
+	{ value: 'lessThan', label: '小于' },
+	{ value: 'greaterOrEqual', label: '大于等于' },
+	{ value: 'lessOrEqual', label: '小于等于' }
 ]
 ]
 
 
 const props = defineProps<Props>()
 const props = defineProps<Props>()
 const emit = defineEmits<Emits>()
 const emit = defineEmits<Emits>()
 
 
-
-
-const conditions = ref<Condition[]>(props.modelValue || [
-    {
-        id: `condition_${Date.now()}`,
-        leftValue: '',
-        operator: '',
-        rightValue: ''
-    }
-])
-
+const conditions = ref<Condition[]>(
+	props.modelValue || [
+		{
+			id: `condition_${Date.now()}`,
+			leftValue: '',
+			operator: '',
+			rightValue: ''
+		}
+	]
+)
 
 
 watch(
 watch(
-    () => props.modelValue,
-    (newVal) => {
-        if (newVal && newVal.length > 0) {
-            conditions.value = newVal
-        }
-    },
-    { deep: true }
+	() => props.modelValue,
+	(newVal) => {
+		if (newVal && newVal.length > 0) {
+			conditions.value = newVal
+		}
+	},
+	{ deep: true }
 )
 )
 
 
 const addCondition = () => {
 const addCondition = () => {
-    conditions.value.push({
-        id: `condition_${Date.now()}`,
-        leftValue: '',
-        operator: '',
-        rightValue: ''
-    })
-    handleConditionChange()
+	conditions.value.push({
+		id: `condition_${Date.now()}`,
+		leftValue: '',
+		operator: '',
+		rightValue: ''
+	})
+	handleConditionChange()
 }
 }
 
 
 const removeCondition = (index: number) => {
 const removeCondition = (index: number) => {
-    conditions.value.splice(index, 1)
-    handleConditionChange()
+	conditions.value.splice(index, 1)
+	handleConditionChange()
 }
 }
 
 
 const handleConditionChange = () => {
 const handleConditionChange = () => {
-    emit('update:modelValue', conditions.value)
+	emit('update:modelValue', conditions.value)
 }
 }
 
 
 // const openVariablePicker = (index: number, side: 'left' | 'right') => {
 // const openVariablePicker = (index: number, side: 'left' | 'right') => {

+ 0 - 1
apps/web/src/components/Sidebar/index.vue

@@ -172,7 +172,6 @@ import { ref, computed, onMounted, onUnmounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
 import { ElMessage } from 'element-plus'
 import SearchDialog from '../SearchDialog/index.vue'
 import SearchDialog from '../SearchDialog/index.vue'
-import { v4 } from 'uuid'
 import TemplateModal from '../TemplateModal/index.vue'
 import TemplateModal from '../TemplateModal/index.vue'
 import CreateWorkflowModal from '@/features/createModal/index.vue'
 import CreateWorkflowModal from '@/features/createModal/index.vue'
 import { applyTheme } from '@/theme'
 import { applyTheme } from '@/theme'

+ 1 - 1
apps/web/src/features/createModal/index.vue

@@ -23,7 +23,7 @@
 							v-model="form.tags"
 							v-model="form.tags"
 							placeholder="按回车键添加标签"
 							placeholder="按回车键添加标签"
 							aria-label="按回车键添加标签"
 							aria-label="按回车键添加标签"
-							:max-tags="5"
+							:max="5"
 						/>
 						/>
 						<span class="tag-tip shrink-0">最多 5 个</span>
 						<span class="tag-tip shrink-0">最多 5 个</span>
 					</div>
 					</div>

+ 6 - 12
apps/web/src/features/nodeLibary/index.vue

@@ -2,6 +2,7 @@
 import { computed, ref, watch } from 'vue'
 import { computed, ref, watch } from 'vue'
 import { nodes, type INodeType } from '@repo/nodes'
 import { nodes, type INodeType } from '@repo/nodes'
 import { Icon } from '@repo/ui'
 import { Icon } from '@repo/ui'
+import { useDragAndDrop } from '@repo/workflow'
 
 
 defineOptions({
 defineOptions({
 	name: 'AddMaterialsPop'
 	name: 'AddMaterialsPop'
@@ -27,11 +28,7 @@ const emit = defineEmits<{
 	'add-node': [value: { type: string }]
 	'add-node': [value: { type: string }]
 }>()
 }>()
 
 
-const normalizeType = (name: string) => {
-	if (name === 'http-request') return 'http'
-	if (name === 'if-else') return 'condition'
-	return name
-}
+const { onDragStart } = useDragAndDrop()
 
 
 const materials = computed<NodeGroup[]>(() => {
 const materials = computed<NodeGroup[]>(() => {
 	const groupMap = new Map<string, NodeGroup>()
 	const groupMap = new Map<string, NodeGroup>()
@@ -51,7 +48,7 @@ const materials = computed<NodeGroup[]>(() => {
 
 
 		group.nodes.push({
 		group.nodes.push({
 			id: node.name,
 			id: node.name,
-			type: normalizeType(node.name),
+			type: node.schema.nodeType,
 			name: node.displayName,
 			name: node.displayName,
 			description: node.description,
 			description: node.description,
 			icon: node.icon,
 			icon: node.icon,
@@ -85,18 +82,15 @@ const onAddNode = (value: NodeItem) => {
 <template>
 <template>
 	<div class="node-lib">
 	<div class="node-lib">
 		<el-tabs v-model="activeGroup" class="node-tabs" stretch>
 		<el-tabs v-model="activeGroup" class="node-tabs" stretch>
-			<el-tab-pane
-				v-for="group in materials"
-				:key="group.id"
-				:label="group.label"
-				:name="group.id"
-			>
+			<el-tab-pane v-for="group in materials" :key="group.id" :label="group.label" :name="group.id">
 				<ul>
 				<ul>
 					<li
 					<li
 						class="tool mb-3 flex items-center"
 						class="tool mb-3 flex items-center"
 						v-for="item in group.nodes"
 						v-for="item in group.nodes"
 						:key="item.id"
 						:key="item.id"
+						:draggable="true"
 						@click="onAddNode(item)"
 						@click="onAddNode(item)"
+						@dragstart="onDragStart($event, item.type)"
 					>
 					>
 						<Icon
 						<Icon
 							:icon="item.icon || 'lucide:square'"
 							:icon="item.icon || 'lucide:square'"

apps/web/src/components/setter/CodeSetter.vue → apps/web/src/features/setter/CodeSetter.vue


apps/web/src/components/setter/ConditionSetter.vue → apps/web/src/features/setter/ConditionSetter.vue


apps/web/src/components/setter/DatabaseSetter.vue → apps/web/src/features/setter/DatabaseSetter.vue


apps/web/src/components/setter/HttpSetter.vue → apps/web/src/features/setter/HttpSetter.vue


apps/web/src/components/setter/index.vue → apps/web/src/features/setter/index.vue


+ 1 - 1
apps/web/src/features/toolbar/index.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
 	<div class="absolute top-0 right-0 p-16px flex flex-col gap-12px">
 	<div class="absolute top-0 right-0 p-16px flex flex-col gap-12px">
 		<el-tooltip content="节点" placement="left">
 		<el-tooltip content="节点" placement="left">
-			<el-popover placement="left-start" width="400px">
+			<el-popover placement="left-start" width="360px">
 				<NodeLibary @add-node="(val) => $emit('create:node', val)" />
 				<NodeLibary @add-node="(val) => $emit('create:node', val)" />
 				<template #reference>
 				<template #reference>
 					<IconButton type="primary" class="ml-12px" icon="lucide:package-plus" square />
 					<IconButton type="primary" class="ml-12px" icon="lucide:package-plus" square />

+ 2 - 0
apps/web/src/types/nprogress.d.ts

@@ -0,0 +1,2 @@
+declare module 'nprogress';
+

+ 2 - 2
apps/web/src/views/Chat.vue

@@ -96,7 +96,7 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { ref, computed, onMounted, nextTick, onBeforeUnmount } from 'vue'
+import { ref, computed, onMounted, nextTick } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { BubbleList, Sender } from 'vue-element-plus-x'
 import { BubbleList, Sender } from 'vue-element-plus-x'
 import { useChatStore } from '@/store/modules/chat.store'
 import { useChatStore } from '@/store/modules/chat.store'
@@ -397,7 +397,7 @@ const formatTime = (timestamp: number) => {
 
 
 		.sidebar-header {
 		.sidebar-header {
 			padding: 13px;
 			padding: 13px;
-				border-bottom: 1px solid var(--border-light);
+			border-bottom: 1px solid var(--border-light);
 
 
 			.new-chat-btn {
 			.new-chat-btn {
 				width: 100%;
 				width: 100%;

+ 58 - 54
apps/web/src/views/Editor.vue

@@ -20,7 +20,7 @@
 					v-model="workflow.tags"
 					v-model="workflow.tags"
 					placeholder="按回车键添加标签"
 					placeholder="按回车键添加标签"
 					aria-label="按回车键添加标签"
 					aria-label="按回车键添加标签"
-					:max-tags="5"
+					:max="5"
 					@blur="showTagInput = false"
 					@blur="showTagInput = false"
 				/>
 				/>
 				<IconButton
 				<IconButton
@@ -48,22 +48,25 @@
 		</div>
 		</div>
 		<el-splitter layout="vertical" class="flex-1">
 		<el-splitter layout="vertical" class="flex-1">
 			<el-splitter-panel>
 			<el-splitter-panel>
-				<Workflow
-					:workflow="workflow"
-					@click:node="handleNodeClick"
-					@create:node="handleNodeCreate"
-					@create:connection="onCreateConnection"
-					@drop="handleDrop"
-					@run="handleRunWorkflow"
-					@run:node="handleRunNode"
-					@update:nodes:position="handleUpdateNodesPosition"
-					@update:node:attrs="handleUpdateNodeProps"
-					@delete:node="handleDeleteNode"
-					@delete:connection="handleDeleteEdge"
-					class="bg-#f5f5f5"
-				>
-					<Toolbar @create:node="handleNodeCreate" @run="handleRunSelectedNode" />
-				</Workflow>
+				<div class="h-full w-full" @drop="onDrop">
+					<Workflow
+						:workflow="workflow"
+						@click:node="handleNodeClick"
+						@create:node="handleNodeCreate"
+						@create:connection:end="onCreateConnection"
+						@drag-and-drop="handleDrop"
+						@run:node="handleRunNode"
+						@update:nodes:position="handleUpdateNodesPosition"
+						@update:node:attrs="handleUpdateNodeProps"
+						@delete:node="handleDeleteNode"
+						@delete:connection="handleDeleteEdge"
+						@dragover="onDragOver"
+						@dragleave="onDragLeave"
+						class="bg-#f5f5f5"
+					>
+						<Toolbar @create:node="handleNodeCreate" @run="handleRunSelectedNode" />
+					</Workflow>
+				</div>
 				<RunWorkflow v-model:visible="runVisible" @run="handleRunSelectedNode" />
 				<RunWorkflow v-model:visible="runVisible" @run="handleRunSelectedNode" />
 				<Setter
 				<Setter
 					:id="nodeID"
 					:id="nodeID"
@@ -82,32 +85,38 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { ref, inject, type CSSProperties, onBeforeUnmount, watch, nextTick } from 'vue'
 import { ref, inject, type CSSProperties, onBeforeUnmount, watch, nextTick } from 'vue'
-import { startNode, endNode, httpNode, conditionNode, databaseNode, codeNode } from '@repo/nodes'
-import { Workflow, type IWorkflow, type XYPosition, type Connection } from '@repo/workflow'
-import { v4 as uuid } from 'uuid'
 import { useRoute, useRouter } from 'vue-router'
 import { useRoute, useRouter } from 'vue-router'
 import { agent } from '@repo/api-service'
 import { agent } from '@repo/api-service'
 
 
-import Setter from '@/components/setter/index.vue'
 import RunWorkflow from '@/components/RunWorkflow/index.vue'
 import RunWorkflow from '@/components/RunWorkflow/index.vue'
 import EditorFooter from '@/features/editorFooter/index.vue'
 import EditorFooter from '@/features/editorFooter/index.vue'
 import Toolbar from '@/features/toolbar/index.vue'
 import Toolbar from '@/features/toolbar/index.vue'
+import Setter from '@/features/setter/index.vue'
 
 
 import { IconButton, Input } from '@repo/ui'
 import { IconButton, Input } from '@repo/ui'
 import { nodeMap } from '@repo/nodes'
 import { nodeMap } from '@repo/nodes'
+import { Workflow, useDragAndDrop } from '@repo/workflow'
 
 
 import { dayjs, ElMessage, ElMessageBox } from 'element-plus'
 import { dayjs, ElMessage, ElMessageBox } from 'element-plus'
 
 
+import type { IWorkflow, XYPosition, Connection } from '@repo/workflow'
+
 const layout = inject<{ setMainStyle: (style: CSSProperties) => void }>('layout')
 const layout = inject<{ setMainStyle: (style: CSSProperties) => void }>('layout')
 
 
 layout?.setMainStyle({
 layout?.setMainStyle({
 	padding: '0px'
 	padding: '0px'
 })
 })
 
 
+const { onDragOver, onDrop, onDragLeave } = useDragAndDrop({
+	addNodes: (node) => {
+		handleNodeCreate(node)
+	}
+})
+
 const footerHeight = ref(32)
 const footerHeight = ref(32)
 const route = useRoute()
 const route = useRoute()
 const router = useRouter()
 const router = useRouter()
-const id = (route.params?.id as string) || uuid()
+const id = route.params?.id as string
 
 
 const projectMap = JSON.parse(localStorage.getItem(`workflow-map`) || '{}') as Record<
 const projectMap = JSON.parse(localStorage.getItem(`workflow-map`) || '{}') as Record<
 	string,
 	string,
@@ -208,7 +217,7 @@ const handleApiResult = (response: any, successMessage?: string, errorMessage?:
 
 
 const buildUpdateNodePayload = (node: any) => {
 const buildUpdateNodePayload = (node: any) => {
 	return {
 	return {
-		id: node.id,
+		...node,
 		appAgentId: workflow.value.id,
 		appAgentId: workflow.value.id,
 		parentId: node.parentId || node.data?.parentId || '',
 		parentId: node.parentId || node.data?.parentId || '',
 		position: node.position || { x: 20, y: 30 },
 		position: node.position || { x: 20, y: 30 },
@@ -349,15 +358,7 @@ const saveAgentMeta = async () => {
 
 
 	try {
 	try {
 		const response = await agent.postAgentDoEditAgent({
 		const response = await agent.postAgentDoEditAgent({
-			data: {
-				id: workflow.value.id,
-				name: workflow.value.name,
-				tags: workflow.value.tags || [],
-				description: workflow.value.description || '',
-				remark: workflow.value.description || '',
-				profilePhoto: workflow.value.profilePhoto,
-				viewPort: workflow.value.viewPort
-			}
+			data: workflow.value
 		})
 		})
 		handleApiResult(response, '智能体已保存', '保存智能体失败')
 		handleApiResult(response, '智能体已保存', '保存智能体失败')
 	} catch (error) {
 	} catch (error) {
@@ -457,9 +458,6 @@ const nodeID = ref('')
 const setterVisible = ref(false)
 const setterVisible = ref(false)
 const runVisible = ref(false)
 const runVisible = ref(false)
 const pendingSetterInit = new Set<string>()
 const pendingSetterInit = new Set<string>()
-const handleRunWorkflow = () => {
-	runVisible.value = true
-}
 
 
 const handleRunSelectedNode = async () => {
 const handleRunSelectedNode = async () => {
 	if (!workflow.value?.id) {
 	if (!workflow.value?.id) {
@@ -480,9 +478,10 @@ const handleRunSelectedNode = async () => {
 	}
 	}
 
 
 	try {
 	try {
-		const response = await agent.postAgentDoTestNodeRunner({
+		const response = await agent.postAgentDoExecute({
 			appAgentId: workflow.value.id,
 			appAgentId: workflow.value.id,
-			id: nodeID.value
+			start_node_id: nodeID.value,
+			is_debugger: true
 		})
 		})
 		runVisible.value = false
 		runVisible.value = false
 		handleApiResult(response, '已提交节点测试', '节点测试失败')
 		handleApiResult(response, '已提交节点测试', '节点测试失败')
@@ -499,9 +498,10 @@ const handleRunNode = async (id: string) => {
 	}
 	}
 
 
 	try {
 	try {
-		const response = await agent.postAgentDoTestNodeRunner({
+		const response = await agent.postAgentDoExecute({
 			appAgentId: workflow.value.id,
 			appAgentId: workflow.value.id,
-			id
+			start_node_id: id,
+			is_debugger: true
 		})
 		})
 		handleApiResult(response, '已提交节点测试', '节点测试失败')
 		handleApiResult(response, '已提交节点测试', '节点测试失败')
 	} catch (error) {
 	} catch (error) {
@@ -509,17 +509,16 @@ const handleRunNode = async (id: string) => {
 		ElMessage.error('节点测试失败')
 		ElMessage.error('节点测试失败')
 	}
 	}
 }
 }
-const handleNodeCreate = (value: { type: string } | string) => {
-	const id = uuid()
+const handleNodeCreate = (value: { type: string; position?: XYPosition } | string) => {
 	if (typeof value === 'string') {
 	if (typeof value === 'string') {
 		if (value === 'stickyNote') {
 		if (value === 'stickyNote') {
 			workflow.value?.nodes.push({
 			workflow.value?.nodes.push({
-				id,
 				type: 'canvas-node',
 				type: 'canvas-node',
 				zIndex: -1,
 				zIndex: -1,
 				position: { x: 600, y: 300 },
 				position: { x: 600, y: 300 },
+				id: 'stickyNote',
 				data: {
 				data: {
-					id,
+					id: '',
 					version: ['1.0.0'],
 					version: ['1.0.0'],
 					inputs: [],
 					inputs: [],
 					outputs: [],
 					outputs: [],
@@ -539,15 +538,16 @@ const handleNodeCreate = (value: { type: string } | string) => {
 
 
 	// 如果存在对应节点则添加
 	// 如果存在对应节点则添加
 	if (nodeToAdd) {
 	if (nodeToAdd) {
+		const position = value.position || nodeToAdd.position
+
 		const newNode = {
 		const newNode = {
 			...nodeToAdd,
 			...nodeToAdd,
+			position,
 			type: 'canvas-node',
 			type: 'canvas-node',
 			data: {
 			data: {
 				...nodeToAdd,
 				...nodeToAdd,
-				id
-			},
-			__pendingCreate: true,
-			id
+				position
+			}
 		}
 		}
 
 
 		agent
 		agent
@@ -557,7 +557,7 @@ const handleNodeCreate = (value: { type: string } | string) => {
 				width: newNode.width,
 				width: newNode.width,
 				height: newNode.height,
 				height: newNode.height,
 				selected: !!newNode.selected,
 				selected: !!newNode.selected,
-				nodeType: newNode.data?.nodeType,
+				nodeType: newNode.data?.nodeType as any,
 				zIndex: newNode.zIndex ?? 1,
 				zIndex: newNode.zIndex ?? 1,
 				parentId: newNode.parentId || ''
 				parentId: newNode.parentId || ''
 			})
 			})
@@ -580,7 +580,10 @@ const handleNodeClick = (id: string, _position: XYPosition) => {
 }
 }
 
 
 const handleDrop = (position: XYPosition, event: DragEvent) => {
 const handleDrop = (position: XYPosition, event: DragEvent) => {
-	console.log('drag and drop at', position, event)
+	const type = event.dataTransfer?.getData('application/x-node-type')
+	if (!type) return
+
+	handleNodeCreate({ type, position })
 }
 }
 
 
 /**
 /**
@@ -610,14 +613,15 @@ const handleDelete = () => {
  * 创建连线
  * 创建连线
  */
  */
 const onCreateConnection = async (connection: Connection) => {
 const onCreateConnection = async (connection: Connection) => {
-	const { source, target, sourceHandle } = connection
+	const { source, target } = connection
+	// TODO: 处理带handle的情况
 
 
 	if (!workflow.value?.edges.some((edge) => edge.source === source && edge.target === target)) {
 	if (!workflow.value?.edges.some((edge) => edge.source === source && edge.target === target)) {
 		const response = await agent.postAgentDoNewEdge({
 		const response = await agent.postAgentDoNewEdge({
 			appAgentId: workflow.value.id,
 			appAgentId: workflow.value.id,
 			source,
 			source,
 			target,
 			target,
-			sourceHandle: sourceHandle!,
+			// sourceHandle: sourceHandle!,
 			zIndex: 1
 			zIndex: 1
 		})
 		})
 
 
@@ -718,9 +722,9 @@ const handleDeleteNode = async (id: string) => {
  */
  */
 const handleDeleteEdge = async (connection: Connection) => {
 const handleDeleteEdge = async (connection: Connection) => {
 	if (connection.id) {
 	if (connection.id) {
-		// await agent.postAgentDoDeleteEdge({
-		// 	id: connection.id
-		// })
+		await agent.postAgentDoDeleteEdge({
+			id: connection.id
+		})
 		await loadAgentWorkflow(workflow.value.id)
 		await loadAgentWorkflow(workflow.value.id)
 	}
 	}
 }
 }

+ 473 - 84
packages/api-service/agent.openapi.json

@@ -22,6 +22,67 @@
 		}
 		}
 	],
 	],
 	"paths": {
 	"paths": {
+		"/api/openapi/doBatchGenerateUUID": {
+			"post": {
+				"summary": "批量生成UUID",
+				"deprecated": false,
+				"description": "",
+				"tags": ["tools"],
+				"parameters": [
+					{
+						"name": "Authorization",
+						"in": "header",
+						"description": "",
+						"example": "bpm_client_1485689273129635840",
+						"schema": {
+							"type": "string",
+							"default": "bpm_client_1485689273129635840"
+						}
+					}
+				],
+				"responses": {
+					"200": {
+						"description": "",
+						"content": {
+							"application/json": {
+								"schema": {
+									"type": "object",
+									"properties": {
+										"isSuccess": {
+											"type": "boolean"
+										},
+										"code": {
+											"type": "integer"
+										},
+										"result": {
+											"type": "array",
+											"items": {
+												"type": "string"
+											}
+										},
+										"isAuthorized": {
+											"type": "boolean"
+										}
+									},
+									"required": ["isSuccess", "code", "result", "isAuthorized"]
+								},
+								"example": {
+									"isSuccess": true,
+									"code": 1,
+									"result": [
+										"a33c9f0a-bc3a-4a25-86ba-080ee6772063",
+										"efab3a9d-e5f6-4339-8d6c-6189b85d984f"
+									],
+									"isAuthorized": true
+								}
+							}
+						},
+						"headers": {}
+					}
+				},
+				"security": []
+			}
+		},
 		"/api/agent/doEditAgent": {
 		"/api/agent/doEditAgent": {
 			"post": {
 			"post": {
 				"summary": "智能体编辑",
 				"summary": "智能体编辑",
@@ -641,55 +702,48 @@
 				}
 				}
 			}
 			}
 		},
 		},
-		"/api/agent/doTestNodeRunner": {
+		"/api/agent/doDeleteAgentNode": {
 			"post": {
 			"post": {
-				"summary": "测试运行智能体节点",
+				"summary": "删除智能体节点",
+				"deprecated": false,
 				"description": "",
 				"description": "",
 				"tags": ["Agent"],
 				"tags": ["Agent"],
 				"parameters": [
 				"parameters": [
 					{
 					{
 						"name": "Authorization",
 						"name": "Authorization",
 						"in": "header",
 						"in": "header",
-						"description": "认证令牌",
-						"required": false,
+						"description": "",
+						"example": "bpm_client_1485689273129635840",
 						"schema": {
 						"schema": {
 							"type": "string",
 							"type": "string",
-							"default": "bpm_client_1473687766939209728",
-							"example": "bpm_client_1473687766939209728"
+							"default": "bpm_client_1485689273129635840"
 						}
 						}
 					}
 					}
 				],
 				],
 				"requestBody": {
 				"requestBody": {
-					"required": true,
 					"content": {
 					"content": {
 						"application/json": {
 						"application/json": {
 							"schema": {
 							"schema": {
 								"type": "object",
 								"type": "object",
 								"properties": {
 								"properties": {
 									"id": {
 									"id": {
-										"type": "string",
-										"format": "uuid"
-									},
-									"appAgentId": {
-										"type": "string",
-										"format": "uuid"
+										"type": "string"
 									}
 									}
 								},
 								},
-								"required": ["id", "appAgentId"]
+								"required": ["id"]
+							},
+							"example": {
+								"id": "492048da-6f33-4a36-adc5-cff4b973b053"
 							}
 							}
 						}
 						}
-					}
+					},
+					"required": true
 				},
 				},
 				"responses": {
 				"responses": {
 					"200": {
 					"200": {
-						"description": "成功响应",
+						"description": "",
 						"content": {
 						"content": {
 							"application/json": {
 							"application/json": {
-								"example": {
-									"isSuccess": true,
-									"code": 1,
-									"isAuthorized": true
-								},
 								"schema": {
 								"schema": {
 									"type": "object",
 									"type": "object",
 									"properties": {
 									"properties": {
@@ -697,24 +751,30 @@
 											"type": "boolean"
 											"type": "boolean"
 										},
 										},
 										"code": {
 										"code": {
-											"type": "integer",
-											"format": "int32"
+											"type": "integer"
 										},
 										},
 										"isAuthorized": {
 										"isAuthorized": {
 											"type": "boolean"
 											"type": "boolean"
 										}
 										}
 									},
 									},
 									"required": ["isSuccess", "code", "isAuthorized"]
 									"required": ["isSuccess", "code", "isAuthorized"]
+								},
+								"example": {
+									"isSuccess": true,
+									"code": 1,
+									"isAuthorized": true
 								}
 								}
 							}
 							}
-						}
+						},
+						"headers": {}
 					}
 					}
-				}
+				},
+				"security": []
 			}
 			}
 		},
 		},
-		"/api/agent/doDeleteAgentNode": {
+		"/api/agent/doNewEdge": {
 			"post": {
 			"post": {
-				"summary": "删除智能体节点",
+				"summary": "新增智能体边缘信息",
 				"deprecated": false,
 				"deprecated": false,
 				"description": "",
 				"description": "",
 				"tags": ["Agent"],
 				"tags": ["Agent"],
@@ -736,14 +796,44 @@
 							"schema": {
 							"schema": {
 								"type": "object",
 								"type": "object",
 								"properties": {
 								"properties": {
-									"id": {
+									"appAgentId": {
+										"type": "string"
+									},
+									"source": {
+										"type": "string"
+									},
+									"sourceHandle": {
+										"type": "string"
+									},
+									"target": {
 										"type": "string"
 										"type": "string"
+									},
+									"zIndex": {
+										"type": "integer"
 									}
 									}
 								},
 								},
-								"required": ["id"]
+								"required": ["appAgentId", "source", "target", "zIndex"]
 							},
 							},
-							"example": {
-								"id": "492048da-6f33-4a36-adc5-cff4b973b053"
+							"examples": {
+								"1": {
+									"value": {
+										"appAgentId": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
+										"source": "492048da-6f33-4a36-adc5-cff4b973b053",
+										"target": "c91eb026-e86a-418f-a865-a98aa60bcf19",
+										"zIndex": 0
+									},
+									"summary": "普通节点"
+								},
+								"2": {
+									"value": {
+										"appAgentId": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
+										"source": "de35b389-3782-474c-9dd9-cb1356dea54b",
+										"sourceHandle": "c2cb978e-fce8-11f0-a59d-266b7b87fca6-1",
+										"target": "6764ede2-2c3d-46bb-ae9a-fb0a892aff84",
+										"zIndex": 0
+									},
+									"summary": "条件分支节点边缘"
+								}
 							}
 							}
 						}
 						}
 					},
 					},
@@ -782,9 +872,9 @@
 				"security": []
 				"security": []
 			}
 			}
 		},
 		},
-		"/api/agent/doNewEdge": {
+		"/api/agent/doDeleteEdge": {
 			"post": {
 			"post": {
-				"summary": "新增智能体边缘信息",
+				"summary": "删除智能体边缘信息",
 				"deprecated": false,
 				"deprecated": false,
 				"description": "",
 				"description": "",
 				"tags": ["Agent"],
 				"tags": ["Agent"],
@@ -793,10 +883,10 @@
 						"name": "Authorization",
 						"name": "Authorization",
 						"in": "header",
 						"in": "header",
 						"description": "",
 						"description": "",
-						"example": "bpm_client_1485689273129635840",
+						"example": "bpm_client_1486435889042165760",
 						"schema": {
 						"schema": {
 							"type": "string",
 							"type": "string",
-							"default": "bpm_client_1485689273129635840"
+							"default": "bpm_client_1486435889042165760"
 						}
 						}
 					}
 					}
 				],
 				],
@@ -806,44 +896,14 @@
 							"schema": {
 							"schema": {
 								"type": "object",
 								"type": "object",
 								"properties": {
 								"properties": {
-									"appAgentId": {
-										"type": "string"
-									},
-									"source": {
-										"type": "string"
-									},
-									"sourceHandle": {
-										"type": "string"
-									},
-									"target": {
+									"id": {
 										"type": "string"
 										"type": "string"
-									},
-									"zIndex": {
-										"type": "integer"
 									}
 									}
 								},
 								},
-								"required": ["appAgentId", "source", "target", "zIndex"]
+								"required": ["id"]
 							},
 							},
-							"examples": {
-								"1": {
-									"value": {
-										"appAgentId": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
-										"source": "492048da-6f33-4a36-adc5-cff4b973b053",
-										"target": "c91eb026-e86a-418f-a865-a98aa60bcf19",
-										"zIndex": 0
-									},
-									"summary": "普通节点"
-								},
-								"2": {
-									"value": {
-										"appAgentId": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
-										"source": "de35b389-3782-474c-9dd9-cb1356dea54b",
-										"sourceHandle": "c2cb978e-fce8-11f0-a59d-266b7b87fca6-1",
-										"target": "6764ede2-2c3d-46bb-ae9a-fb0a892aff84",
-										"zIndex": 0
-									},
-									"summary": "条件分支节点边缘"
-								}
+							"example": {
+								"id": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8"
 							}
 							}
 						}
 						}
 					},
 					},
@@ -893,10 +953,10 @@
 						"name": "Authorization",
 						"name": "Authorization",
 						"in": "header",
 						"in": "header",
 						"description": "",
 						"description": "",
-						"example": "bpm_client_1485689273129635840",
+						"example": "bpm_client_1486435889042165760",
 						"schema": {
 						"schema": {
 							"type": "string",
 							"type": "string",
-							"default": "bpm_client_1485689273129635840"
+							"default": "bpm_client_1486435889042165760"
 						}
 						}
 					}
 					}
 				],
 				],
@@ -952,24 +1012,51 @@
 				"security": []
 				"security": []
 			}
 			}
 		},
 		},
-		"/api/openapi/doBatchGenerateUUID": {
+		"/api/agent/doExecute": {
 			"post": {
 			"post": {
-				"summary": "批量生成UUID",
+				"summary": "运行智能体",
 				"deprecated": false,
 				"deprecated": false,
 				"description": "",
 				"description": "",
-				"tags": ["tools"],
+				"tags": ["Agent"],
 				"parameters": [
 				"parameters": [
 					{
 					{
 						"name": "Authorization",
 						"name": "Authorization",
 						"in": "header",
 						"in": "header",
 						"description": "",
 						"description": "",
-						"example": "bpm_client_1485689273129635840",
+						"example": "bpm_client_1486435889042165760",
 						"schema": {
 						"schema": {
 							"type": "string",
 							"type": "string",
-							"default": "bpm_client_1485689273129635840"
+							"default": "bpm_client_1486435889042165760"
 						}
 						}
 					}
 					}
 				],
 				],
+				"requestBody": {
+					"content": {
+						"application/json": {
+							"schema": {
+								"type": "object",
+								"properties": {
+									"appAgentId": {
+										"type": "string"
+									},
+									"start_node_id": {
+										"type": "string"
+									},
+									"is_debugger": {
+										"type": "boolean"
+									}
+								},
+								"required": ["appAgentId", "start_node_id", "is_debugger"]
+							},
+							"example": {
+								"appAgentId": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
+								"start_node_id": "492048da-6f33-4a36-adc5-cff4b973b053",
+								"is_debugger": true
+							}
+						}
+					},
+					"required": true
+				},
 				"responses": {
 				"responses": {
 					"200": {
 					"200": {
 						"description": "",
 						"description": "",
@@ -985,10 +1072,235 @@
 											"type": "integer"
 											"type": "integer"
 										},
 										},
 										"result": {
 										"result": {
-											"type": "array",
-											"items": {
-												"type": "string"
-											}
+											"type": "object",
+											"properties": {
+												"agent": {
+													"type": "object",
+													"properties": {
+														"conversation_variables": {
+															"type": "array",
+															"items": {
+																"type": "string"
+															}
+														},
+														"creationTime": {
+															"type": "string"
+														},
+														"creatorUserId": {
+															"type": "string"
+														},
+														"env_variables": {
+															"type": "array",
+															"items": {
+																"type": "object",
+																"properties": {
+																	"is_require": {
+																		"type": "boolean"
+																	},
+																	"name": {
+																		"type": "string"
+																	},
+																	"type": {
+																		"type": "string"
+																	},
+																	"value": {
+																		"type": "string"
+																	}
+																}
+															}
+														},
+														"id": {
+															"type": "string"
+														},
+														"isDeleted": {
+															"type": "boolean"
+														},
+														"name": {
+															"type": "string"
+														},
+														"profilePhoto": {
+															"type": "string"
+														},
+														"remark": {
+															"type": "string"
+														},
+														"updateTime": {
+															"type": "string"
+														},
+														"viewPort": {
+															"type": "object",
+															"properties": {
+																"x": {
+																	"type": "integer"
+																},
+																"y": {
+																	"type": "integer"
+																},
+																"zoom": {
+																	"type": "integer"
+																}
+															},
+															"required": ["x", "y", "zoom"]
+														}
+													},
+													"required": [
+														"conversation_variables",
+														"creationTime",
+														"creatorUserId",
+														"env_variables",
+														"id",
+														"isDeleted",
+														"name",
+														"profilePhoto",
+														"remark",
+														"updateTime",
+														"viewPort"
+													]
+												},
+												"runVariable": {
+													"type": "object",
+													"properties": {
+														"session": {
+															"type": "object",
+															"properties": {}
+														},
+														"492048da-6f33-4a36-adc5-cff4b973b053": {
+															"type": "object",
+															"properties": {
+																"headers": {
+																	"type": "object",
+																	"properties": {
+																		"transfer-Encoding": {
+																			"type": "string"
+																		},
+																		"access-Control-Expose-Headers": {
+																			"type": "string"
+																		},
+																		"server": {
+																			"type": "string"
+																		},
+																		"access-Control-Allow-Credentials": {
+																			"type": "string"
+																		},
+																		"connection": {
+																			"type": "string"
+																		},
+																		"access-Control-Max-Age": {
+																			"type": "string"
+																		},
+																		"date": {
+																			"type": "string"
+																		},
+																		"x-proxy-pass": {
+																			"type": "string"
+																		},
+																		"content-Type": {
+																			"type": "string"
+																		}
+																	},
+																	"required": [
+																		"transfer-Encoding",
+																		"access-Control-Expose-Headers",
+																		"server",
+																		"access-Control-Allow-Credentials",
+																		"connection",
+																		"access-Control-Max-Age",
+																		"date",
+																		"x-proxy-pass",
+																		"content-Type"
+																	]
+																},
+																"status_code": {
+																	"type": "integer"
+																},
+																"body": {
+																	"type": "string"
+																},
+																"$execute_result": {
+																	"type": "object",
+																	"properties": {
+																		"code": {
+																			"type": "integer"
+																		},
+																		"data": {
+																			"type": "object",
+																			"properties": {
+																				"cookieList": {
+																					"type": "array",
+																					"items": {
+																						"type": "string"
+																					}
+																				},
+																				"error": {
+																					"type": "boolean"
+																				},
+																				"statusCode": {
+																					"type": "integer"
+																				},
+																				"success": {
+																					"type": "boolean"
+																				},
+																				"throwableMsg": {
+																					"type": "string"
+																				}
+																			},
+																			"required": [
+																				"cookieList",
+																				"error",
+																				"statusCode",
+																				"success",
+																				"throwableMsg"
+																			]
+																		},
+																		"error": {
+																			"type": "boolean"
+																		},
+																		"isSelected": {
+																			"type": "boolean"
+																		},
+																		"msg": {
+																			"type": "string"
+																		},
+																		"success": {
+																			"type": "boolean"
+																		},
+																		"ts": {
+																			"type": "string"
+																		}
+																	},
+																	"required": [
+																		"code",
+																		"data",
+																		"error",
+																		"isSelected",
+																		"msg",
+																		"success",
+																		"ts"
+																	]
+																}
+															},
+															"required": ["headers", "status_code", "body", "$execute_result"]
+														},
+														"env": {
+															"type": "object",
+															"properties": {
+																"api_address": {
+																	"type": "string"
+																}
+															},
+															"required": ["api_address"]
+														}
+													},
+													"required": ["session", "492048da-6f33-4a36-adc5-cff4b973b053", "env"]
+												},
+												"run_nodes": {
+													"type": "array",
+													"items": {
+														"type": "string"
+													}
+												}
+											},
+											"required": ["agent", "runVariable", "run_nodes"]
 										},
 										},
 										"isAuthorized": {
 										"isAuthorized": {
 											"type": "boolean"
 											"type": "boolean"
@@ -999,10 +1311,87 @@
 								"example": {
 								"example": {
 									"isSuccess": true,
 									"isSuccess": true,
 									"code": 1,
 									"code": 1,
-									"result": [
-										"a33c9f0a-bc3a-4a25-86ba-080ee6772063",
-										"efab3a9d-e5f6-4339-8d6c-6189b85d984f"
-									],
+									"result": {
+										"agent": {
+											"conversation_variables": [],
+											"creationTime": "2026-01-27 19:02:30",
+											"creatorUserId": "7F8A2BFE-402D-4499-9BB8-2EF7FFC7B993",
+											"env_variables": [
+												{
+													"is_require": false,
+													"name": "api_address",
+													"type": "string",
+													"value": "http://shalu-componenttesting-admin-dev.shalu.com"
+												}
+											],
+											"id": "b3a4aabb-a6b8-47f3-8a32-f45930f7d7b8",
+											"isDeleted": false,
+											"name": "测试智能体",
+											"profilePhoto": "1111",
+											"remark": "描述",
+											"updateTime": "2026-01-27 19:02:30",
+											"viewPort": {
+												"x": 10,
+												"y": 10,
+												"zoom": 1
+											}
+										},
+										"runVariable": {
+											"c91eb026-e86a-418f-a865-a98aa60bcf19": {
+												"result": ["11", "22", "33"],
+												"$execute_result": {
+													"code": 1,
+													"error": false,
+													"isSelected": false,
+													"msg": "SUCCESS",
+													"success": true,
+													"ts": "2026-03-04 20:18:17"
+												}
+											},
+											"cae0c279-c1aa-40b6-9702-1df2af104a9b": {
+												"aa": [11, 22, 33],
+												"ifout": false
+											},
+											"session": {},
+											"492048da-6f33-4a36-adc5-cff4b973b053": {
+												"headers": {
+													"access-Control-Expose-Headers": "*,Content-Disposition",
+													"server": "nginx/1.26.1",
+													"access-Control-Allow-Credentials": "true",
+													"connection": "keep-alive",
+													"content-Length": "0",
+													"access-Control-Max-Age": "18000L",
+													"date": "Wed, 04 Mar 2026 12:18:17 GMT",
+													"x-proxy-pass": "shalu-componenttesting-admin-dev.shalu.com"
+												},
+												"status_code": 200,
+												"body": "",
+												"$execute_result": {
+													"code": 1,
+													"data": {
+														"cookieList": [],
+														"error": false,
+														"statusCode": 200,
+														"success": true,
+														"throwableMsg": ""
+													},
+													"error": false,
+													"isSelected": false,
+													"msg": "SUCCESS",
+													"success": true,
+													"ts": "2026-03-04 20:18:17"
+												}
+											},
+											"env": {
+												"api_address": "http://shalu-componenttesting-admin-dev.shalu.com"
+											}
+										},
+										"run_nodes": [
+											"492048da-6f33-4a36-adc5-cff4b973b053",
+											"c91eb026-e86a-418f-a865-a98aa60bcf19",
+											"cae0c279-c1aa-40b6-9702-1df2af104a9b"
+										]
+									},
 									"isAuthorized": true
 									"isAuthorized": true
 								}
 								}
 							}
 							}

+ 247 - 175
packages/api-service/servers/api/agent.ts

@@ -4,214 +4,286 @@ import request from '@repo/api-client'
 
 
 /** 删除智能体节点 POST /api/agent/doDeleteAgentNode */
 /** 删除智能体节点 POST /api/agent/doDeleteAgentNode */
 export async function postAgentDoDeleteAgentNode(
 export async function postAgentDoDeleteAgentNode(
-	body: {
-		id: string
-	},
-	options?: { [key: string]: any }
+  body: {
+    id: string
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doDeleteAgentNode',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doDeleteAgentNode',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
+}
+
+/** 删除智能体边缘信息 POST /api/agent/doDeleteEdge */
+export async function postAgentDoDeleteEdge(
+  body: {
+    id: string
+  },
+  options?: { [key: string]: any }
+) {
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doDeleteEdge',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 智能体编辑 POST /api/agent/doEditAgent */
 /** 智能体编辑 POST /api/agent/doEditAgent */
 export async function postAgentDoEditAgent(options?: { [key: string]: any }) {
 export async function postAgentDoEditAgent(options?: { [key: string]: any }) {
-	return request<{ isSuccess: boolean; code: number; result: string; isAuthorized: boolean }>(
-		'/api/agent/doEditAgent',
-		{
-			method: 'POST',
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; result: string; isAuthorized: boolean }>(
+    '/api/agent/doEditAgent',
+    {
+      method: 'POST',
+      ...(options || {})
+    }
+  )
+}
+
+/** 运行智能体 POST /api/agent/doExecute */
+export async function postAgentDoExecute(
+  body: {
+    appAgentId: string
+    start_node_id: string
+    is_debugger: boolean
+  },
+  options?: { [key: string]: any }
+) {
+  return request<{
+    isSuccess: boolean
+    code: number
+    result: {
+      agent: {
+        conversation_variables: string[]
+        creationTime: string
+        creatorUserId: string
+        env_variables: { is_require?: boolean; name?: string; type?: string; value?: string }[]
+        id: string
+        isDeleted: boolean
+        name: string
+        profilePhoto: string
+        remark: string
+        updateTime: string
+        viewPort: { x: number; y: number; zoom: number }
+      }
+      runVariable: {
+        session: Record<string, any>
+        '492048da-6f33-4a36-adc5-cff4b973b053': {
+          headers: {
+            'transfer-Encoding': string
+            'access-Control-Expose-Headers': string
+            server: string
+            'access-Control-Allow-Credentials': string
+            connection: string
+            'access-Control-Max-Age': string
+            date: string
+            'x-proxy-pass': string
+            'content-Type': string
+          }
+          status_code: number
+          body: string
+          $execute_result: {
+            code: number
+            data: {
+              cookieList: string[]
+              error: boolean
+              statusCode: number
+              success: boolean
+              throwableMsg: string
+            }
+            error: boolean
+            isSelected: boolean
+            msg: string
+            success: boolean
+            ts: string
+          }
+        }
+        env: { api_address: string }
+      }
+      run_nodes: string[]
+    }
+    isAuthorized: boolean
+  }>('/api/agent/doExecute', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    data: body,
+    ...(options || {})
+  })
 }
 }
 
 
 /** 智能体添加节点 POST /api/agent/doNewAgentNode */
 /** 智能体添加节点 POST /api/agent/doNewAgentNode */
 export async function postAgentDoNewAgentNode(
 export async function postAgentDoNewAgentNode(
-	body: {
-		appAgentId: string
-		position: { x: number; y: number }
-		width: number
-		height: number
-		selected: boolean
-		nodeType: string
-		zIndex: number
-		parentId: string
-	},
-	options?: { [key: string]: any }
+  body: {
+    appAgentId: string
+    position: { x: number; y: number }
+    width: number
+    height: number
+    selected: boolean
+    nodeType: 'custom' | 'start' | 'end' | 'condition' | 'task' | 'http-request'
+    zIndex: number
+    parentId: string
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doNewAgentNode',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doNewAgentNode',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 新增智能体边缘信息 POST /api/agent/doNewEdge */
 /** 新增智能体边缘信息 POST /api/agent/doNewEdge */
 export async function postAgentDoNewEdge(
 export async function postAgentDoNewEdge(
-	body: {
-		appAgentId: string
-		source: string
-		sourceHandle?: string
-		target: string
-		zIndex: number
-	},
-	options?: { [key: string]: any }
+  body: {
+    appAgentId: string
+    source: string
+    sourceHandle?: string
+    target: string
+    zIndex: number
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doNewEdge',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doNewEdge',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 保存智能体变量 POST /api/agent/doSaveAgentVariables */
 /** 保存智能体变量 POST /api/agent/doSaveAgentVariables */
 export async function postAgentDoSaveAgentVariables(
 export async function postAgentDoSaveAgentVariables(
-	body: {
-		appAgentId: string
-		conversation_variables: string[]
-		env_variables: {
-			name: string
-			value: string
-			type: 'string' | 'number' | 'boolean' | 'object' | 'array'
-		}[]
-	},
-	options?: { [key: string]: any }
+  body: {
+    appAgentId: string
+    conversation_variables: string[]
+    env_variables: {
+      name: string
+      value: string
+      type: 'string' | 'number' | 'boolean' | 'object' | 'array'
+    }[]
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; result: string; isAuthorized: boolean }>(
-		'/api/agent/doSaveAgentVariables',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; result: string; isAuthorized: boolean }>(
+    '/api/agent/doSaveAgentVariables',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 选中智能体边缘 POST /api/agent/doSelectedEdge */
 /** 选中智能体边缘 POST /api/agent/doSelectedEdge */
 export async function postAgentDoSelectedEdge(
 export async function postAgentDoSelectedEdge(
-	body: {
-		id: string
-	},
-	options?: { [key: string]: any }
-) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doSelectedEdge',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
-}
-
-/** 测试运行智能体节点 POST /api/agent/doTestNodeRunner */
-export async function postAgentDoTestNodeRunner(
-	body: {
-		id: string
-		appAgentId: string
-	},
-	options?: { [key: string]: any }
+  body: {
+    id: string
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doTestNodeRunner',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doSelectedEdge',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 更新智能体节点 POST /api/agent/doUpdateAgentNode */
 /** 更新智能体节点 POST /api/agent/doUpdateAgentNode */
 export async function postAgentDoUpdateAgentNode(
 export async function postAgentDoUpdateAgentNode(
-	body: {
-		id: string
-		appAgentId: string
-		parentId: string
-		position: { x: number; y: number }
-		width: number
-		height: number
-		selected: boolean
-		nodeType: 'custom' | 'start' | 'end' | 'condition' | 'task' | 'http-request'
-		zIndex: number
-		data: Record<string, any>
-	},
-	options?: { [key: string]: any }
+  body: {
+    id: string
+    appAgentId: string
+    parentId: string
+    position: { x: number; y: number }
+    width: number
+    height: number
+    selected: boolean
+    nodeType: 'custom' | 'start' | 'end' | 'condition' | 'task' | 'http-request'
+    zIndex: number
+    data: Record<string, any>
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
-		'/api/agent/doUpdateAgentNode',
-		{
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/json'
-			},
-			data: body,
-			...(options || {})
-		}
-	)
+  return request<{ isSuccess: boolean; code: number; isAuthorized: boolean }>(
+    '/api/agent/doUpdateAgentNode',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: body,
+      ...(options || {})
+    }
+  )
 }
 }
 
 
 /** 获取智能体信息 POST /api/agent/getAgentInfo */
 /** 获取智能体信息 POST /api/agent/getAgentInfo */
 export async function postAgentGetAgentInfo(
 export async function postAgentGetAgentInfo(
-	body: {
-		id: string
-	},
-	options?: { [key: string]: any }
+  body: {
+    id: string
+  },
+  options?: { [key: string]: any }
 ) {
 ) {
-	return request<{
-		isSuccess: boolean
-		code: number
-		result: {
-			conversation_variables: string[]
-			edges: string[]
-			env_variables: {
-				is_require?: boolean
-				name: string
-				type: 'string' | 'number' | 'boolean' | 'object' | 'array'
-				value: string
-			}[]
-			id: string
-			name: string
-			nodes: API.AgentNode[]
-			profilePhoto: string
-			viewPort: { x: number; y: number; zoom: number }
-		}
-		isAuthorized: boolean
-	}>('/api/agent/getAgentInfo', {
-		method: 'POST',
-		headers: {
-			'Content-Type': 'application/json'
-		},
-		data: body,
-		...(options || {})
-	})
+  return request<{
+    isSuccess: boolean
+    code: number
+    result: {
+      conversation_variables: string[]
+      edges: string[]
+      env_variables: {
+        is_require?: boolean
+        name: string
+        type: 'string' | 'number' | 'boolean' | 'object' | 'array'
+        value: string
+      }[]
+      id: string
+      name: string
+      nodes: API.AgentNode[]
+      profilePhoto: string
+      viewPort: { x: number; y: number; zoom: number }
+    }
+    isAuthorized: boolean
+  }>('/api/agent/getAgentInfo', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    data: body,
+    ...(options || {})
+  })
 }
 }

+ 3 - 3
packages/api-service/servers/api/index.ts

@@ -2,9 +2,9 @@
 /* eslint-disable */
 /* eslint-disable */
 // API 更新时间:
 // API 更新时间:
 // API 唯一标识:
 // API 唯一标识:
-import * as agent from './agent'
 import * as tools from './tools'
 import * as tools from './tools'
+import * as agent from './agent'
 export default {
 export default {
-  agent,
-  tools
+  tools,
+  agent
 }
 }

+ 171 - 0
packages/nodes/Interface.ts

@@ -166,3 +166,174 @@ export interface INodeType {
 export const NodeConnectionTypes = {
 export const NodeConnectionTypes = {
 	main: 'main'
 	main: 'main'
 }
 }
+
+/**
+ * 节点变量类型
+ */
+type NodeVariableType =
+	| 'string'
+	| 'number'
+	| 'boolean'
+	| 'object'
+	| 'array[string]'
+	| 'array[number]'
+	| 'array[boolean]'
+	| 'array[object]'
+
+/**
+ * 节点变量值类型
+ */
+type NodeVariableValueType = 'constant' | 'variable'
+
+/**
+ * 节点变量
+ */
+interface NodeVariable {
+	name: string
+	describe: string
+	type: NodeVariableType
+	value: any
+	value_type?: NodeVariableValueType
+}
+
+/**
+ * 节点重试配置
+ */
+interface NodeRetryConfig {
+	retry_enabled: boolean
+	max_retries: number
+	retry_interval: number // milliseconds
+}
+
+/**
+ * 节点错误处理策略
+ */
+type NodeErrorStrategy = 'none' | 'default-value' | 'fail-branch'
+
+/**
+ * 节点类型
+ */
+type NodeType =
+	| 'http-request'
+	| 'code'
+	| 'if-else'
+	| 'iteration'
+	| 'iteration-start'
+	| 'list-operator'
+	| 'loop'
+	| 'loop-start'
+	| 'end'
+	| string
+
+/**
+ * 节点公共配置信息
+ */
+export interface INodeDataBaseSchema {
+	/**
+	 * 节点类型
+	 */
+	type: NodeType
+	/**
+	 * 标题
+	 */
+	title: string
+	/**
+	 * 是否在迭代中
+	 */
+	isInIteration: boolean
+	/**
+	 * 迭代id
+	 */
+	iteration_id: string
+	/**
+	 * 是否在循环中
+	 */
+	isInLoop: boolean
+	/**
+	 * 循环id
+	 */
+	loop_id: string
+	/**
+	 * 输入变量列表
+	 */
+	variables: NodeVariable[]
+	/**
+	 * 重试配置
+	 */
+	retry_config: NodeRetryConfig
+	/**
+	 * 错误处理策略
+	 */
+	error_strategy: NodeErrorStrategy
+	/**
+	 * 失败分支节点id
+	 */
+	fail_branch_node_id: string
+	/**
+	 * 默认值
+	 */
+	default_value: NodeVariable[]
+	/**
+	 * 输出变量是否可修改
+	 */
+	output_can_alter: boolean
+	/**
+	 * 输出变量列表
+	 */
+	outputs: NodeVariable[]
+}
+
+/**
+ * 条件项类型
+ */
+export interface ConditionType {
+	/**
+	 * 比较操作符
+	 * 可选值: contains, not_contains, start_with, end_with, is, is_not, empty, not_empty, =, !=, >, <, ≥, ≤, all_of
+	 */
+	comparison_operator:
+		| 'contains'
+		| 'not_contains'
+		| 'start_with'
+		| 'end_with'
+		| 'is'
+		| 'is_not'
+		| 'empty'
+		| 'not_empty'
+		| '='
+		| '!='
+		| '>'
+		| '<'
+		| '≥'
+		| '≤'
+		| 'all_of'
+
+	/**
+	 * 左值,支持常量或#{}方式的动态变量
+	 */
+	left_value: string
+
+	/**
+	 * 右值,支持常量或#{}方式的动态变量
+	 */
+	right_value: string
+
+	/**
+	 * 右值列表,预留
+	 */
+	right_value_list: string[]
+
+	/**
+	 * 变量类型
+	 * 可选值: string | number | boolean | object | array[string] | array[number] | array[boolean] | array[object]
+	 */
+	varType:
+		| 'string'
+		| 'number'
+		| 'boolean'
+		| 'object'
+		| 'array[string]'
+		| 'array[number]'
+		| 'array[boolean]'
+		| 'array[object]'
+}

+ 1 - 2
packages/nodes/index.ts

@@ -6,7 +6,6 @@
  * @Describe: file describe
  * @Describe: file describe
  */
  */
 
 
-export *  from './materials';
-export * from './nodes/chat/chat.node'
+export * from './materials'
 
 
 export * from './Interface'
 export * from './Interface'

+ 12 - 5
packages/nodes/materials/code.tsx

@@ -1,4 +1,9 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { INodeDataBaseSchema, NodeConnectionTypes, type INodeType } from '../Interface'
+
+export type CodeData = INodeDataBaseSchema & {
+	code: string
+	code_language: string
+}
 
 
 export const codeNode: INodeType = {
 export const codeNode: INodeType = {
 	version: ['1'],
 	version: ['1'],
@@ -25,10 +30,12 @@ export const codeNode: INodeType = {
 		zIndex: 1,
 		zIndex: 1,
 		data: {
 		data: {
 			// 代码配置数据
 			// 代码配置数据
+			code: '',
+			code_language: 'javascript'
 		}
 		}
-	},
-	// 节点渲染
-	render(data) {
-		return <div></div>
 	}
 	}
+	// 节点渲染
+	// render() {
+	// 	return <div></div>
+	// }
 }
 }

+ 17 - 2
packages/nodes/materials/condition.ts

@@ -1,4 +1,19 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import {
+	NodeConnectionTypes,
+	type INodeType,
+	type INodeDataBaseSchema,
+	type ConditionType
+} from '../Interface'
+
+type CaseType = {
+	id: string
+	logical_operator: 'and' | 'or'
+	conditions: ConditionType[]
+}
+
+export type ConditionData = INodeDataBaseSchema & {
+	cases: CaseType[]
+}
 
 
 export const conditionNode: INodeType = {
 export const conditionNode: INodeType = {
 	version: ['1'],
 	version: ['1'],
@@ -9,7 +24,7 @@ export const conditionNode: INodeType = {
 	icon: 'lucide:trending-up-down',
 	icon: 'lucide:trending-up-down',
 	iconColor: '#b33be6',
 	iconColor: '#b33be6',
 	inputs: [NodeConnectionTypes.main],
 	inputs: [NodeConnectionTypes.main],
-	outputs: (data: any) => {
+	outputs: () => {
 		return [NodeConnectionTypes.main]
 		return [NodeConnectionTypes.main]
 	},
 	},
 	// 业务数据
 	// 业务数据

+ 3 - 1
packages/nodes/materials/end.ts

@@ -1,4 +1,6 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { NodeConnectionTypes, type INodeType, type INodeDataBaseSchema } from '../Interface'
+
+export type EndData = INodeDataBaseSchema & {}
 
 
 export const endNode: INodeType = {
 export const endNode: INodeType = {
 	version: ['1'],
 	version: ['1'],

+ 17 - 32
packages/nodes/materials/http.ts

@@ -1,41 +1,29 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { NodeConnectionTypes, type INodeType, type INodeDataBaseSchema } from '../Interface'
 
 
-export type HttpData = {
-	outputs: Array<{
-		name: 'body' | 'status_code' | 'headers'
-		describe: string
-		type: 'string' | 'number' | 'object'
-	}>
-	output_can_alter: boolean
-	variables: any[]
-	method: 'post'
+export type HttpRequestData = INodeDataBaseSchema & {
+	method: 'get' | 'post' | 'put' | 'delete' | 'patch'
 	ssl_verify: boolean
 	ssl_verify: boolean
-	isInIteration: boolean
-	default_value: any[]
 	body: {
 	body: {
-		type: 'json'
+		type: string
 		data: Array<{
 		data: Array<{
 			key: string
 			key: string
-			type: 'text'
+			type: 'text' | 'file' | string
 			value: string
 			value: string
 		}>
 		}>
 	}
 	}
-	params: any[]
+	params: Array<{
+		key: string
+		value: string
+	}>
 	title: string
 	title: string
-	type: 'http-request'
-	error_strategy: 'none' | string
-	retry_config: {
-		max_retries: number
-		retry_enabled: boolean
-		retry_interval: number
-	}
 	url: string
 	url: string
 	authorization: {
 	authorization: {
-		type: string
+		type: 'none' | 'api-key' | string
 		config: {
 		config: {
-			api_key: string
-			header: string
-			type: string
+			api_key?: string
+			header?: string
+			type?: 'basic' | 'bearer' | 'custom' | string
+			[key: string]: any
 		}
 		}
 	}
 	}
 	timeout_config: {
 	timeout_config: {
@@ -47,9 +35,6 @@ export type HttpData = {
 		name: string
 		name: string
 		value: string
 		value: string
 	}>
 	}>
-	selected: boolean
-	desc: string
-	isInLoop: boolean
 }
 }
 
 
 export const httpNode: INodeType = {
 export const httpNode: INodeType = {
@@ -61,13 +46,13 @@ export const httpNode: INodeType = {
 	icon: 'lucide:link',
 	icon: 'lucide:link',
 	iconColor: '#9373ee',
 	iconColor: '#9373ee',
 	inputs: [NodeConnectionTypes.main],
 	inputs: [NodeConnectionTypes.main],
-	outputs: (data: HttpData) => {
+	outputs: (data: HttpRequestData) => {
 		// todo: 判断异常处理,如果是分支,添加异常出口
 		// todo: 判断异常处理,如果是分支,添加异常出口
-		return data?.error_strategy === 'exception'
+		return data?.error_strategy === 'fail-branch'
 			? [NodeConnectionTypes.main, NodeConnectionTypes.main]
 			? [NodeConnectionTypes.main, NodeConnectionTypes.main]
 			: [NodeConnectionTypes.main]
 			: [NodeConnectionTypes.main]
 	},
 	},
-	validate: (data: HttpData) => {
+	validate: (data: HttpRequestData) => {
 		return !!data?.url.trim() ? false : '请填写URL'
 		return !!data?.url.trim() ? false : '请填写URL'
 	},
 	},
 	// 业务数据
 	// 业务数据

+ 49 - 2
packages/nodes/materials/iteration.ts

@@ -1,6 +1,53 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { NodeConnectionTypes, type INodeType, type INodeDataBaseSchema } from '../Interface'
 
 
-export type IterationData = {}
+export type IterationData = INodeDataBaseSchema & {
+	/**
+	 * 错误处理模式
+	 * terminated: 终止
+	 * continue-on-error: 出错继续
+	 * remove-abnormal-output: 移除异常输出
+	 */
+	error_handle_mode: 'terminated' | 'continue-on-error' | 'remove-abnormal-output'
+
+	/**
+	 * 是否并行
+	 */
+	is_parallel: boolean
+
+	/**
+	 * 并行数量
+	 */
+	parallel_nums: number
+
+	/**
+	 * 扁平化输出
+	 */
+	flatten_output: boolean
+
+	/**
+	 * 开始节点id
+	 */
+	start_node_id: string
+
+	/**
+	 * 迭代输出变量
+	 */
+	output_iteration_variable: Array<{
+		name: string
+		describe: string
+		type:
+			| 'string'
+			| 'number'
+			| 'boolean'
+			| 'object'
+			| 'array[string]'
+			| 'array[number]'
+			| 'array[boolean]'
+			| 'array[object]'
+		value: any
+		value_type?: 'constant' | 'variable'
+	}>
+}
 
 
 export const iterationNode: INodeType = {
 export const iterationNode: INodeType = {
 	version: ['1'],
 	version: ['1'],

+ 57 - 2
packages/nodes/materials/list.ts

@@ -1,6 +1,61 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { NodeConnectionTypes, type INodeType, type INodeDataBaseSchema } from '../Interface'
 
 
-export type ListData = {}
+export type ListData = INodeDataBaseSchema & {
+	/**
+	 * 提取配置
+	 */
+	extract_by: {
+		enabled: boolean
+		serial: string
+	}
+
+	/**
+	 * 过滤配置
+	 */
+	filter_by: {
+		enabled: boolean
+		conditions: Array<{
+			comparison_operator:
+				| 'contains'
+				| 'not_contains'
+				| 'start_with'
+				| 'end_with'
+				| 'is'
+				| 'is_not'
+				| 'empty'
+				| 'not_empty'
+				| '='
+				| '!='
+				| '>'
+				| '<'
+				| '≥'
+				| '≤'
+				| 'all_of'
+			left_value: string
+			right_value: string
+			right_value_list: string[]
+			varType:
+				| 'string'
+				| 'number'
+				| 'boolean'
+				| 'object'
+				| 'array[string]'
+				| 'array[number]'
+				| 'array[boolean]'
+				| 'array[object]'
+		}>
+	}
+
+	limit: {
+		enabled: boolean
+		size: number
+	}
+
+	order_by: {
+		key: string
+		value: 'asc' | 'desc' | ''
+	}
+}
 
 
 export const listNode: INodeType = {
 export const listNode: INodeType = {
 	version: ['1'],
 	version: ['1'],

+ 55 - 2
packages/nodes/materials/loop.ts

@@ -1,6 +1,59 @@
-import { NodeConnectionTypes, type INodeType } from '../Interface'
+import { NodeConnectionTypes, type INodeType, type INodeDataBaseSchema } from '../Interface'
 
 
-export type LoopData = {}
+export type LoopData = INodeDataBaseSchema & {
+	/**
+	 * 循环次数
+	 */
+	loop_count: number
+
+	/**
+	 * 循环终止条件
+	 */
+	break_conditions: Array<{
+		comparison_operator:
+			| 'contains'
+			| 'not_contains'
+			| 'start_with'
+			| 'end_with'
+			| 'is'
+			| 'is_not'
+			| 'empty'
+			| 'not_empty'
+			| '='
+			| '!='
+			| '>'
+			| '<'
+			| '≥'
+			| '≤'
+			| 'all_of'
+		left_value: string
+		right_value: string
+		varType:
+			| 'string'
+			| 'number'
+			| 'boolean'
+			| 'object'
+			| 'array[string]'
+			| 'array[number]'
+			| 'array[boolean]'
+			| 'array[object]'
+	}>
+
+	/**
+	 * 逻辑操作(and/or)
+	 */
+	logical_operator: 'and' | 'or'
+
+	/**
+	 * 开始节点id
+	 */
+	start_node_id: string
+
+	/**
+	 * 错误处理模式(terminated/continue-on-error/remove-abnormal-output)
+	 */
+	error_handle_mode: 'terminated' | 'continue-on-error' | 'remove-abnormal-output'
+}
 
 
 export const loopNode: INodeType = {
 export const loopNode: INodeType = {
 	version: ['1'],
 	version: ['1'],

+ 0 - 17
packages/nodes/nodes/chat/chat.node.ts

@@ -1,17 +0,0 @@
-import type { INodeData, INodeType } from '../../Interface'
-import { NodeConnectionTypes } from '../../Interface'
-
-export class Chat implements INodeType {
-	schema: INodeData = {
-		version: ['1.0.0'],
-		displayName: '用户输入',
-		name: 'chart',
-		description: '通过用户输入开启流程处理',
-		icon: 'fluent:comment-multiple-28-regular',
-		iconColor: '#296dff',
-		inputs: [],
-		outputs: [NodeConnectionTypes.main]
-	}
-
-	// 其他方法和属性
-}

+ 0 - 18
packages/nodes/nodes/if/if.node.ts

@@ -1,18 +0,0 @@
-import type { INodeData, INodeType } from '../../Interface'
-import { NodeConnectionTypes } from '../../Interface'
-
-export class Chat implements INodeType {
-	schema: INodeData = {
-		version: ['1.0.0'],
-		displayName: '条件判断',
-		name: 'if',
-		description: '通过条件判断拆分多个流程分支',
-		icon: 'roentgen:guidepost',
-		iconColor: '#108e49',
-		inputs: [NodeConnectionTypes.main],
-		outputs: [NodeConnectionTypes.main, NodeConnectionTypes.main],
-		outputNames: ['true', 'false']
-	}
-
-	// 其他方法和属性
-}

+ 2 - 1
packages/workflow/index.ts

@@ -1,4 +1,5 @@
 import Workflow from './src/Workflow.vue'
 import Workflow from './src/Workflow.vue'
+import useDragAndDrop from './src/hooks/useDragAndDrop'
 
 
-export { Workflow }
+export { Workflow, useDragAndDrop }
 export * from './src/Interface'
 export * from './src/Interface'

+ 12 - 10
packages/workflow/src/components/Canvas.vue

@@ -57,6 +57,8 @@ const emit = defineEmits<{
 	'duplicate:nodes': [ids: string[]]
 	'duplicate:nodes': [ids: string[]]
 	'cut:nodes': [ids: string[]]
 	'cut:nodes': [ids: string[]]
 	'drag-and-drop': [position: XYPosition, event: DragEvent]
 	'drag-and-drop': [position: XYPosition, event: DragEvent]
+	dragover: [event: DragEvent]
+	dragleave: [event: DragEvent]
 	'delete:connection': [connection: Connection]
 	'delete:connection': [connection: Connection]
 	'create:connection:start': [handle: ConnectStartEvent]
 	'create:connection:start': [handle: ConnectStartEvent]
 	'create:connection': [connection: Connection]
 	'create:connection': [connection: Connection]
@@ -67,7 +69,6 @@ const emit = defineEmits<{
 		event?: MouseEvent
 		event?: MouseEvent
 	]
 	]
 	'click:connection:add': [connection: Connection]
 	'click:connection:add': [connection: Connection]
-	run: []
 }>()
 }>()
 
 
 const props = withDefaults(
 const props = withDefaults(
@@ -195,10 +196,17 @@ const onNodeDoubleClick = ({ node, event }: NodeMouseEvent) => {
 
 
 function onDrop(event: DragEvent) {
 function onDrop(event: DragEvent) {
 	const position = getProjectedPosition(event)
 	const position = getProjectedPosition(event)
-
 	emit('drag-and-drop', position, event)
 	emit('drag-and-drop', position, event)
 }
 }
 
 
+function onDragOver(event: DragEvent) {
+	emit('dragover', event)
+}
+
+function onDragLeave(event: DragEvent) {
+	emit('dragleave', event)
+}
+
 const onZoomIn = () => {
 const onZoomIn = () => {
 	zoomIn()
 	zoomIn()
 }
 }
@@ -296,13 +304,6 @@ function onNodesInitialized() {
 	}
 	}
 }
 }
 
 
-/**
- * Handle
- */
-const handleRun = () => {
-	emit('run')
-}
-
 onMounted(() => {
 onMounted(() => {
 	fitView()
 	fitView()
 })
 })
@@ -332,6 +333,8 @@ defineExpose({
 		@node-double-click="onNodeDoubleClick"
 		@node-double-click="onNodeDoubleClick"
 		@node-drag-stop="onNodeDragStop"
 		@node-drag-stop="onNodeDragStop"
 		@drop="onDrop"
 		@drop="onDrop"
+		@dragover="onDragOver"
+		@dragleave="onDragLeave"
 		@connect="onConnect"
 		@connect="onConnect"
 		@connect-start="onConnectStart"
 		@connect-start="onConnectStart"
 		@connect-end="onConnectEnd"
 		@connect-end="onConnectEnd"
@@ -388,7 +391,6 @@ defineExpose({
 			@zoom-to-fit="onZoomToFit"
 			@zoom-to-fit="onZoomToFit"
 			@reset-zoom="onResetZoom"
 			@reset-zoom="onResetZoom"
 			@add-node="onAddNode"
 			@add-node="onAddNode"
-			@run="handleRun"
 			@toggle-minimap="onToggleMinimap"
 			@toggle-minimap="onToggleMinimap"
 		/>
 		/>
 
 

+ 1 - 3
packages/workflow/src/components/elements/control-bar/CanvasControlBar.vue

@@ -2,7 +2,6 @@
 import { Controls } from '@vue-flow/controls'
 import { Controls } from '@vue-flow/controls'
 import { Icon } from '@iconify/vue'
 import { Icon } from '@iconify/vue'
 import { ElButton } from 'element-plus'
 import { ElButton } from 'element-plus'
-import type { SourceType } from '@repo/nodes'
 
 
 const emit = defineEmits<{
 const emit = defineEmits<{
 	'reset-zoom': []
 	'reset-zoom': []
@@ -11,9 +10,8 @@ const emit = defineEmits<{
 	'zoom-to-fit': []
 	'zoom-to-fit': []
 	'tidy-up': []
 	'tidy-up': []
 	'toggle-zoom-mode': []
 	'toggle-zoom-mode': []
-	'add-node': [value: SourceType | string]
+	'add-node': [value: { type: string } | string]
 	'toggle-minimap': []
 	'toggle-minimap': []
-	run: []
 }>()
 }>()
 
 
 function onResetZoom() {
 function onResetZoom() {

+ 8 - 4
packages/workflow/src/components/elements/nodes/CanvasNode.vue

@@ -37,12 +37,14 @@ const createEndpoint = (data: {
 	count: number
 	count: number
 	offsetAxis: 'top' | 'left'
 	offsetAxis: 'top' | 'left'
 	position: Position
 	position: Position
+	type: 'source' | 'target'
 }): CanvasElementPortWithRenderData => {
 }): CanvasElementPortWithRenderData => {
-	const { port, index, count, offsetAxis, position } = data
+	const { port, index, count, offsetAxis, position, type } = data
+	console.log(port, 'port')
 
 
 	return {
 	return {
 		...port,
 		...port,
-		handleId: `${port.type}-${index}`,
+		handleId: port?.id || type,
 		position,
 		position,
 		connectionsCount: count,
 		connectionsCount: count,
 		isConnecting: false,
 		isConnecting: false,
@@ -65,7 +67,8 @@ const inputs = computed(() => {
 			index,
 			index,
 			count: inputs.length,
 			count: inputs.length,
 			offsetAxis: 'top',
 			offsetAxis: 'top',
-			position: Position.Left
+			position: Position.Left,
+			type: 'target'
 		})
 		})
 	)
 	)
 })
 })
@@ -82,7 +85,8 @@ const outputs = computed(() => {
 			index,
 			index,
 			count: outputs.length,
 			count: outputs.length,
 			offsetAxis: 'top',
 			offsetAxis: 'top',
-			position: Position.Right
+			position: Position.Right,
+			type: 'source'
 		})
 		})
 	)
 	)
 })
 })

+ 98 - 0
packages/workflow/src/hooks/useDragAndDrop.ts

@@ -0,0 +1,98 @@
+import { useVueFlow } from '@vue-flow/core'
+import { ref, watch } from 'vue'
+import type { XYPosition } from '@vue-flow/core'
+
+/**
+ * In a real world scenario you'd want to avoid creating refs in a global scope like this as they might not be cleaned up properly.
+ * @type {{draggedType: Ref<string|null>, isDragOver: Ref<boolean>, isDragging: Ref<boolean>}}
+ */
+const state = {
+	/**
+	 * The type of the node being dragged.
+	 */
+	draggedType: ref<string | null>(null),
+	isDragOver: ref(false),
+	isDragging: ref(false)
+}
+
+export default function useDragAndDrop(options?: {
+	addNodes: (nodes: { type: string; position: XYPosition }) => void
+}) {
+	const { draggedType, isDragOver, isDragging } = state
+	const { addNodes } = options || {}
+
+	const { screenToFlowCoordinate } = useVueFlow()
+
+	watch(isDragging, (dragging) => {
+		document.body.style.userSelect = dragging ? 'none' : ''
+	})
+
+	function onDragStart(event: DragEvent, type: string) {
+		if (event.dataTransfer) {
+			event.dataTransfer.setData('application/vueflow', type)
+			event.dataTransfer.effectAllowed = 'move'
+		}
+
+		draggedType.value = type
+		isDragging.value = true
+
+		document.addEventListener('drop', onDragEnd)
+	}
+
+	/**
+	 * Handles the drag over event.
+	 *
+	 * @param {DragEvent} event
+	 */
+	function onDragOver(event: DragEvent) {
+		event.preventDefault()
+
+		if (draggedType.value) {
+			isDragOver.value = true
+
+			if (event.dataTransfer) {
+				event.dataTransfer.dropEffect = 'move'
+			}
+		}
+	}
+
+	function onDragLeave() {
+		isDragOver.value = false
+	}
+
+	function onDragEnd() {
+		isDragging.value = false
+		isDragOver.value = false
+		draggedType.value = null
+		document.removeEventListener('drop', onDragEnd)
+	}
+
+	/**
+	 * Handles the drop event.
+	 *
+	 * @param {DragEvent} event
+	 */
+	function onDrop(event: DragEvent) {
+		const position = screenToFlowCoordinate({
+			x: event.clientX,
+			y: event.clientY
+		})
+
+		const newNode = {
+			type: draggedType.value!,
+			position
+		}
+
+		addNodes?.(newNode)
+	}
+
+	return {
+		draggedType,
+		isDragOver,
+		isDragging,
+		onDragStart,
+		onDragLeave,
+		onDragOver,
+		onDrop
+	}
+}

+ 99 - 63
pnpm-lock.yaml

@@ -144,7 +144,7 @@ importers:
         version: link:../../packages/nodes
         version: link:../../packages/nodes
       '@vitejs/plugin-vue-jsx':
       '@vitejs/plugin-vue-jsx':
         specifier: ^5.1.3
         specifier: ^5.1.3
-        version: 5.1.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))
+        version: 5.1.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))
       axios:
       axios:
         specifier: ^1.13.2
         specifier: ^1.13.2
         version: 1.13.2
         version: 1.13.2
@@ -197,9 +197,12 @@ importers:
       '@types/lodash-es':
       '@types/lodash-es':
         specifier: ^4.17.12
         specifier: ^4.17.12
         version: 4.17.12
         version: 4.17.12
+      '@types/nprogress':
+        specifier: ^0.2.3
+        version: 0.2.3
       '@vitejs/plugin-vue':
       '@vitejs/plugin-vue':
         specifier: ^6.0.1
         specifier: ^6.0.1
-        version: 6.0.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))
+        version: 6.0.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))
       '@vue/tsconfig':
       '@vue/tsconfig':
         specifier: ^0.8.1
         specifier: ^0.8.1
         version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
         version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
@@ -214,7 +217,7 @@ importers:
         version: 5.9.3
         version: 5.9.3
       unocss:
       unocss:
         specifier: ^66.6.0
         specifier: ^66.6.0
-        version: 66.6.0(postcss@5.2.18)(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))
+        version: 66.6.0(postcss@5.2.18)(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
       unplugin-auto-import:
       unplugin-auto-import:
         specifier: ^21.0.0
         specifier: ^21.0.0
         version: 21.0.0(@vueuse/core@14.2.0(vue@3.5.27(typescript@5.9.3)))
         version: 21.0.0(@vueuse/core@14.2.0(vue@3.5.27(typescript@5.9.3)))
@@ -226,13 +229,13 @@ importers:
         version: 31.0.0(vue@3.5.27(typescript@5.9.3))
         version: 31.0.0(vue@3.5.27(typescript@5.9.3))
       vite:
       vite:
         specifier: npm:rolldown-vite@7.2.5
         specifier: npm:rolldown-vite@7.2.5
-        version: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+        version: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
       vite-plugin-monaco-editor:
       vite-plugin-monaco-editor:
         specifier: ^1.1.0
         specifier: ^1.1.0
         version: 1.1.0(monaco-editor@0.55.1)
         version: 1.1.0(monaco-editor@0.55.1)
       vite-plugin-svg-icons:
       vite-plugin-svg-icons:
         specifier: ^2.0.1
         specifier: ^2.0.1
-        version: 2.0.1(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))
+        version: 2.0.1(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
       vue-tsc:
       vue-tsc:
         specifier: ^3.1.4
         specifier: ^3.1.4
         version: 3.2.2(typescript@5.9.3)
         version: 3.2.2(typescript@5.9.3)
@@ -257,7 +260,7 @@ importers:
         version: 6.14.0
         version: 6.14.0
       '@umijs/openapi':
       '@umijs/openapi':
         specifier: ^1.14.1
         specifier: ^1.14.1
-        version: 1.14.1(typescript@5.9.3)
+        version: 1.14.1(chokidar@5.0.0)(typescript@5.9.3)
 
 
   packages/api-service:
   packages/api-service:
     devDependencies:
     devDependencies:
@@ -269,7 +272,7 @@ importers:
         version: link:../typescript-config
         version: link:../typescript-config
       '@umijs/openapi':
       '@umijs/openapi':
         specifier: ^1.14.1
         specifier: ^1.14.1
-        version: 1.14.1(typescript@5.9.3)
+        version: 1.14.1(chokidar@5.0.0)(typescript@5.9.3)
 
 
   packages/eslint-config:
   packages/eslint-config:
     devDependencies:
     devDependencies:
@@ -314,7 +317,7 @@ importers:
         version: 4.5.1
         version: 4.5.1
       less-loader:
       less-loader:
         specifier: ^12.3.0
         specifier: ^12.3.0
-        version: 12.3.0(@rspack/core@1.7.3)(less@4.5.1)
+        version: 12.3.0(@rspack/core@1.7.3(@swc/helpers@0.5.18))(less@4.5.1)
     devDependencies:
     devDependencies:
       '@repo/nodes':
       '@repo/nodes':
         specifier: workspace:*
         specifier: workspace:*
@@ -386,13 +389,13 @@ importers:
         version: 4.5.1
         version: 4.5.1
       less-loader:
       less-loader:
         specifier: ^12.3.0
         specifier: ^12.3.0
-        version: 12.3.0(@rspack/core@1.7.3)(less@4.5.1)
+        version: 12.3.0(@rspack/core@1.7.3(@swc/helpers@0.5.18))(less@4.5.1)
       normalize.css:
       normalize.css:
         specifier: ^8.0.1
         specifier: ^8.0.1
         version: 8.0.1
         version: 8.0.1
       unocss:
       unocss:
         specifier: ^66.6.0
         specifier: ^66.6.0
-        version: 66.6.0(postcss@8.5.6)(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))
+        version: 66.6.0(postcss@8.5.6)(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
       vue:
       vue:
         specifier: ^3.5.24
         specifier: ^3.5.24
         version: 3.5.27(typescript@5.9.3)
         version: 3.5.27(typescript@5.9.3)
@@ -411,7 +414,7 @@ importers:
         version: 24.10.9
         version: 24.10.9
       '@vitejs/plugin-vue':
       '@vitejs/plugin-vue':
         specifier: ^6.0.1
         specifier: ^6.0.1
-        version: 6.0.3(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))
+        version: 6.0.3(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))
       '@vue/tsconfig':
       '@vue/tsconfig':
         specifier: ^0.8.1
         specifier: ^0.8.1
         version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
         version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
@@ -420,7 +423,7 @@ importers:
         version: 5.9.3
         version: 5.9.3
       vite:
       vite:
         specifier: npm:rolldown-vite@7.2.5
         specifier: npm:rolldown-vite@7.2.5
-        version: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)
+        version: rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
       vue-tsc:
       vue-tsc:
         specifier: ^3.1.4
         specifier: ^3.1.4
         version: 3.2.2(typescript@5.9.3)
         version: 3.2.2(typescript@5.9.3)
@@ -1059,24 +1062,28 @@ packages:
     engines: {node: '>=14.21.3'}
     engines: {node: '>=14.21.3'}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@biomejs/cli-linux-arm64@2.3.11':
   '@biomejs/cli-linux-arm64@2.3.11':
     resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==}
     resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==}
     engines: {node: '>=14.21.3'}
     engines: {node: '>=14.21.3'}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@biomejs/cli-linux-x64-musl@2.3.11':
   '@biomejs/cli-linux-x64-musl@2.3.11':
     resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==}
     resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==}
     engines: {node: '>=14.21.3'}
     engines: {node: '>=14.21.3'}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@biomejs/cli-linux-x64@2.3.11':
   '@biomejs/cli-linux-x64@2.3.11':
     resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==}
     resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==}
     engines: {node: '>=14.21.3'}
     engines: {node: '>=14.21.3'}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@biomejs/cli-win32-arm64@2.3.11':
   '@biomejs/cli-win32-arm64@2.3.11':
     resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==}
     resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==}
@@ -2193,24 +2200,28 @@ packages:
     engines: {node: ^20.19.0 || >=22.12.0}
     engines: {node: ^20.19.0 || >=22.12.0}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
   '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
     resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==}
     resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==}
     engines: {node: ^20.19.0 || >=22.12.0}
     engines: {node: ^20.19.0 || >=22.12.0}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
   '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
     resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==}
     resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==}
     engines: {node: ^20.19.0 || >=22.12.0}
     engines: {node: ^20.19.0 || >=22.12.0}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
   '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
     resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==}
     resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==}
     engines: {node: ^20.19.0 || >=22.12.0}
     engines: {node: ^20.19.0 || >=22.12.0}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@rolldown/binding-openharmony-arm64@1.0.0-beta.50':
   '@rolldown/binding-openharmony-arm64@1.0.0-beta.50':
     resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==}
     resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==}
@@ -2279,21 +2290,25 @@ packages:
     resolution: {integrity: sha512-SodEX3+1/GLz0LobX9cY1QdjJ1NftSEh4C2vGpr71iA3MS9HyXuw4giqSeRQ4DpCybqpdS/3RLjVqFQEfGpcnw==}
     resolution: {integrity: sha512-SodEX3+1/GLz0LobX9cY1QdjJ1NftSEh4C2vGpr71iA3MS9HyXuw4giqSeRQ4DpCybqpdS/3RLjVqFQEfGpcnw==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@rspack/binding-linux-arm64-musl@1.7.3':
   '@rspack/binding-linux-arm64-musl@1.7.3':
     resolution: {integrity: sha512-ydD2fNdEy+G7EYJ/a3FfdFZPfrLj/UnZocCNlZTTSHEhu+jURdQk0hwV11CvL+sjnKU5e/8IVMGUzhu3Gu8Ghg==}
     resolution: {integrity: sha512-ydD2fNdEy+G7EYJ/a3FfdFZPfrLj/UnZocCNlZTTSHEhu+jURdQk0hwV11CvL+sjnKU5e/8IVMGUzhu3Gu8Ghg==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@rspack/binding-linux-x64-gnu@1.7.3':
   '@rspack/binding-linux-x64-gnu@1.7.3':
     resolution: {integrity: sha512-adnDbUqafSAI6/N6vZ+iONSo1W3yUpnNtJqP3rVp7+YdABhUpbOhtaY37qpIJ3uFajXctYFyISPrb4MWl1M9Yg==}
     resolution: {integrity: sha512-adnDbUqafSAI6/N6vZ+iONSo1W3yUpnNtJqP3rVp7+YdABhUpbOhtaY37qpIJ3uFajXctYFyISPrb4MWl1M9Yg==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@rspack/binding-linux-x64-musl@1.7.3':
   '@rspack/binding-linux-x64-musl@1.7.3':
     resolution: {integrity: sha512-5jnjdODk5HCUFPN6rTaFukynDU4Fn9eCL+4TSp6mqo6YAnfnJEuzDjfetA8t3aQFcAs7WriQfNwvdcA4HvYtbA==}
     resolution: {integrity: sha512-5jnjdODk5HCUFPN6rTaFukynDU4Fn9eCL+4TSp6mqo6YAnfnJEuzDjfetA8t3aQFcAs7WriQfNwvdcA4HvYtbA==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@rspack/binding-wasm32-wasi@1.7.3':
   '@rspack/binding-wasm32-wasi@1.7.3':
     resolution: {integrity: sha512-WLQK0ksUzMkVeGoHAMIxenmeEU5tMvFDK36Aip7VRj7T6vZTcAwvbMwc38QrIAvlG7dqWoxgPQi35ba1igNNDw==}
     resolution: {integrity: sha512-WLQK0ksUzMkVeGoHAMIxenmeEU5tMvFDK36Aip7VRj7T6vZTcAwvbMwc38QrIAvlG7dqWoxgPQi35ba1igNNDw==}
@@ -2633,6 +2648,9 @@ packages:
   '@types/node@25.1.0':
   '@types/node@25.1.0':
     resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==}
     resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==}
 
 
+  '@types/nprogress@0.2.3':
+    resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
+
   '@types/prop-types@15.7.15':
   '@types/prop-types@15.7.15':
     resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
     resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
 
 
@@ -2873,41 +2891,49 @@ packages:
     resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
     resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
   '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
     resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
     resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
   '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
     resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
     resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
     cpu: [ppc64]
     cpu: [ppc64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
   '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
     resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
     resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
     cpu: [riscv64]
     cpu: [riscv64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
   '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
     resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
     resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
     cpu: [riscv64]
     cpu: [riscv64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
   '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
     resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
     resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
     cpu: [s390x]
     cpu: [s390x]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
   '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
     resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
     resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   '@unrs/resolver-binding-linux-x64-musl@1.11.1':
   '@unrs/resolver-binding-linux-x64-musl@1.11.1':
     resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
     resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   '@unrs/resolver-binding-wasm32-wasi@1.11.1':
   '@unrs/resolver-binding-wasm32-wasi@1.11.1':
     resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
     resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
@@ -5112,24 +5138,28 @@ packages:
     engines: {node: '>= 12.0.0'}
     engines: {node: '>= 12.0.0'}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   lightningcss-linux-arm64-musl@1.31.1:
   lightningcss-linux-arm64-musl@1.31.1:
     resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
     resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
     engines: {node: '>= 12.0.0'}
     engines: {node: '>= 12.0.0'}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   lightningcss-linux-x64-gnu@1.31.1:
   lightningcss-linux-x64-gnu@1.31.1:
     resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
     resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
     engines: {node: '>= 12.0.0'}
     engines: {node: '>= 12.0.0'}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [glibc]
 
 
   lightningcss-linux-x64-musl@1.31.1:
   lightningcss-linux-x64-musl@1.31.1:
     resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
     resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
     engines: {node: '>= 12.0.0'}
     engines: {node: '>= 12.0.0'}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
+    libc: [musl]
 
 
   lightningcss-win32-arm64-msvc@1.31.1:
   lightningcss-win32-arm64-msvc@1.31.1:
     resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
     resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
@@ -7206,17 +7236,17 @@ snapshots:
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  '@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1))':
+  '@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@8.57.1)':
     dependencies:
     dependencies:
       '@babel/core': 7.28.6
       '@babel/core': 7.28.6
       '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1
       '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1
-      eslint: 9.39.1(jiti@2.6.1)
+      eslint: 8.57.1
       eslint-visitor-keys: 2.1.0
       eslint-visitor-keys: 2.1.0
       semver: 6.3.1
       semver: 6.3.1
 
 
   '@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))':
   '@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))':
     dependencies:
     dependencies:
-      '@babel/eslint-parser': 7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1))
+      '@babel/eslint-parser': 7.19.1(@babel/core@7.28.6)(eslint@8.57.1)
       eslint: 9.39.1(jiti@2.6.1)
       eslint: 9.39.1(jiti@2.6.1)
       eslint-rule-composer: 0.3.0
       eslint-rule-composer: 0.3.0
 
 
@@ -8945,13 +8975,13 @@ snapshots:
   '@flowgram.ai/eslint-config@1.0.7(@types/node@18.19.130)(jiti@2.6.1)(typescript@5.9.3)':
   '@flowgram.ai/eslint-config@1.0.7(@types/node@18.19.130)(jiti@2.6.1)(typescript@5.9.3)':
     dependencies:
     dependencies:
       '@babel/core': 7.28.6
       '@babel/core': 7.28.6
-      '@babel/eslint-parser': 7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1))
+      '@babel/eslint-parser': 7.19.1(@babel/core@7.28.6)(eslint@8.57.1)
       '@babel/eslint-plugin': 7.27.1(@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
       '@babel/eslint-plugin': 7.27.1(@babel/eslint-parser@7.19.1(@babel/core@7.28.6)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
       '@babel/preset-env': 7.20.2(@babel/core@7.28.6)
       '@babel/preset-env': 7.20.2(@babel/core@7.28.6)
       '@babel/preset-react': 7.13.13(@babel/core@7.28.6)
       '@babel/preset-react': 7.13.13(@babel/core@7.28.6)
       '@eslint/eslintrc': 3.3.3
       '@eslint/eslintrc': 3.3.3
       '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
       '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
-      '@typescript-eslint/parser': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
+      '@typescript-eslint/parser': 8.50.0(eslint@8.57.1)(typescript@5.9.3)
       eslint: 9.39.1(jiti@2.6.1)
       eslint: 9.39.1(jiti@2.6.1)
       eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@2.6.1))
       eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@2.6.1))
       eslint-define-config: 1.12.0
       eslint-define-config: 1.12.0
@@ -10215,6 +10245,8 @@ snapshots:
     dependencies:
     dependencies:
       undici-types: 7.16.0
       undici-types: 7.16.0
 
 
+  '@types/nprogress@0.2.3': {}
+
   '@types/prop-types@15.7.15': {}
   '@types/prop-types@15.7.15': {}
 
 
   '@types/qs@6.14.0': {}
   '@types/qs@6.14.0': {}
@@ -10274,7 +10306,7 @@ snapshots:
   '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)':
   '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)':
     dependencies:
     dependencies:
       '@eslint-community/regexpp': 4.12.2
       '@eslint-community/regexpp': 4.12.2
-      '@typescript-eslint/parser': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
+      '@typescript-eslint/parser': 8.50.0(eslint@8.57.1)(typescript@5.9.3)
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
       '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
       '@typescript-eslint/utils': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
       '@typescript-eslint/utils': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
@@ -10287,27 +10319,27 @@ snapshots:
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  '@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.2)':
+  '@typescript-eslint/parser@8.50.0(eslint@8.57.1)(typescript@5.9.3)':
     dependencies:
     dependencies:
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/types': 8.50.0
       '@typescript-eslint/types': 8.50.0
-      '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.2)
+      '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
       '@typescript-eslint/visitor-keys': 8.50.0
       '@typescript-eslint/visitor-keys': 8.50.0
       debug: 4.4.3(supports-color@5.5.0)
       debug: 4.4.3(supports-color@5.5.0)
-      eslint: 9.39.1(jiti@2.6.1)
-      typescript: 5.9.2
+      eslint: 8.57.1
+      typescript: 5.9.3
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  '@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)':
+  '@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.2)':
     dependencies:
     dependencies:
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/scope-manager': 8.50.0
       '@typescript-eslint/types': 8.50.0
       '@typescript-eslint/types': 8.50.0
-      '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
+      '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.2)
       '@typescript-eslint/visitor-keys': 8.50.0
       '@typescript-eslint/visitor-keys': 8.50.0
       debug: 4.4.3(supports-color@5.5.0)
       debug: 4.4.3(supports-color@5.5.0)
       eslint: 9.39.1(jiti@2.6.1)
       eslint: 9.39.1(jiti@2.6.1)
-      typescript: 5.9.3
+      typescript: 5.9.2
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
@@ -10432,7 +10464,7 @@ snapshots:
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  '@umijs/openapi@1.14.1(typescript@5.9.3)':
+  '@umijs/openapi@1.14.1(chokidar@5.0.0)(typescript@5.9.3)':
     dependencies:
     dependencies:
       chalk: 4.1.2
       chalk: 4.1.2
       cosmiconfig: 9.0.0(typescript@5.9.3)
       cosmiconfig: 9.0.0(typescript@5.9.3)
@@ -10444,7 +10476,7 @@ snapshots:
       mockjs: 1.1.0
       mockjs: 1.1.0
       node-fetch: 2.7.0
       node-fetch: 2.7.0
       number-to-words: 1.2.4
       number-to-words: 1.2.4
-      nunjucks: 3.2.4
+      nunjucks: 3.2.4(chokidar@5.0.0)
       openapi3-ts: 2.0.2
       openapi3-ts: 2.0.2
       prettier: 2.8.8
       prettier: 2.8.8
       reserved-words: 0.1.2
       reserved-words: 0.1.2
@@ -10458,21 +10490,21 @@ snapshots:
 
 
   '@ungap/structured-clone@1.3.0': {}
   '@ungap/structured-clone@1.3.0': {}
 
 
-  '@unocss/astro@66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))':
+  '@unocss/astro@66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))':
     dependencies:
     dependencies:
       '@unocss/core': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/reset': 66.6.0
       '@unocss/reset': 66.6.0
-      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
     optionalDependencies:
     optionalDependencies:
-      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
 
 
-  '@unocss/astro@66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))':
+  '@unocss/astro@66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))':
     dependencies:
     dependencies:
       '@unocss/core': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/reset': 66.6.0
       '@unocss/reset': 66.6.0
-      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
     optionalDependencies:
     optionalDependencies:
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
 
 
   '@unocss/cli@66.6.0':
   '@unocss/cli@66.6.0':
     dependencies:
     dependencies:
@@ -10611,7 +10643,7 @@ snapshots:
     dependencies:
     dependencies:
       '@unocss/core': 66.6.0
       '@unocss/core': 66.6.0
 
 
-  '@unocss/vite@66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))':
+  '@unocss/vite@66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))':
     dependencies:
     dependencies:
       '@jridgewell/remapping': 2.3.5
       '@jridgewell/remapping': 2.3.5
       '@unocss/config': 66.6.0
       '@unocss/config': 66.6.0
@@ -10622,9 +10654,9 @@ snapshots:
       pathe: 2.0.3
       pathe: 2.0.3
       tinyglobby: 0.2.15
       tinyglobby: 0.2.15
       unplugin-utils: 0.3.1
       unplugin-utils: 0.3.1
-      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
 
 
-  '@unocss/vite@66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))':
+  '@unocss/vite@66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))':
     dependencies:
     dependencies:
       '@jridgewell/remapping': 2.3.5
       '@jridgewell/remapping': 2.3.5
       '@unocss/config': 66.6.0
       '@unocss/config': 66.6.0
@@ -10635,7 +10667,7 @@ snapshots:
       pathe: 2.0.3
       pathe: 2.0.3
       tinyglobby: 0.2.15
       tinyglobby: 0.2.15
       unplugin-utils: 0.3.1
       unplugin-utils: 0.3.1
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
 
 
   '@unrs/resolver-binding-android-arm-eabi@1.11.1':
   '@unrs/resolver-binding-android-arm-eabi@1.11.1':
     optional: true
     optional: true
@@ -10696,28 +10728,28 @@ snapshots:
   '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
   '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
     optional: true
     optional: true
 
 
-  '@vitejs/plugin-vue-jsx@5.1.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))':
+  '@vitejs/plugin-vue-jsx@5.1.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))':
     dependencies:
     dependencies:
       '@babel/core': 7.28.6
       '@babel/core': 7.28.6
       '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6)
       '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6)
       '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
       '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6)
       '@rolldown/pluginutils': 1.0.0-rc.2
       '@rolldown/pluginutils': 1.0.0-rc.2
       '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.28.6)
       '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.28.6)
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
       vue: 3.5.27(typescript@5.9.3)
       vue: 3.5.27(typescript@5.9.3)
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  '@vitejs/plugin-vue@6.0.3(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))':
+  '@vitejs/plugin-vue@6.0.3(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))':
     dependencies:
     dependencies:
       '@rolldown/pluginutils': 1.0.0-beta.53
       '@rolldown/pluginutils': 1.0.0-beta.53
-      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
       vue: 3.5.27(typescript@5.9.3)
       vue: 3.5.27(typescript@5.9.3)
 
 
-  '@vitejs/plugin-vue@6.0.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))(vue@3.5.27(typescript@5.9.3))':
+  '@vitejs/plugin-vue@6.0.3(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))(vue@3.5.27(typescript@5.9.3))':
     dependencies:
     dependencies:
       '@rolldown/pluginutils': 1.0.0-beta.53
       '@rolldown/pluginutils': 1.0.0-beta.53
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
       vue: 3.5.27(typescript@5.9.3)
       vue: 3.5.27(typescript@5.9.3)
 
 
   '@volar/language-core@2.4.27':
   '@volar/language-core@2.4.27':
@@ -12118,14 +12150,13 @@ snapshots:
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
-  eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)):
+  eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1):
     dependencies:
     dependencies:
       debug: 3.2.7
       debug: 3.2.7
     optionalDependencies:
     optionalDependencies:
-      '@typescript-eslint/parser': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
-      eslint: 9.39.1(jiti@2.6.1)
+      '@typescript-eslint/parser': 8.50.0(eslint@8.57.1)(typescript@5.9.3)
+      eslint: 8.57.1
       eslint-import-resolver-node: 0.3.9
       eslint-import-resolver-node: 0.3.9
-      eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color
 
 
@@ -12145,7 +12176,7 @@ snapshots:
       doctrine: 2.1.0
       doctrine: 2.1.0
       eslint: 8.57.1
       eslint: 8.57.1
       eslint-import-resolver-node: 0.3.9
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+      eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1)
       hasown: 2.0.2
       hasown: 2.0.2
       is-core-module: 2.16.1
       is-core-module: 2.16.1
       is-glob: 4.0.3
       is-glob: 4.0.3
@@ -12157,7 +12188,7 @@ snapshots:
       string.prototype.trimend: 1.0.9
       string.prototype.trimend: 1.0.9
       tsconfig-paths: 3.15.0
       tsconfig-paths: 3.15.0
     optionalDependencies:
     optionalDependencies:
-      '@typescript-eslint/parser': 8.50.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
+      '@typescript-eslint/parser': 8.50.0(eslint@8.57.1)(typescript@5.9.3)
     transitivePeerDependencies:
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - eslint-import-resolver-webpack
@@ -13237,7 +13268,7 @@ snapshots:
 
 
   layout-base@2.0.1: {}
   layout-base@2.0.1: {}
 
 
-  less-loader@12.3.0(@rspack/core@1.7.3)(less@4.5.1):
+  less-loader@12.3.0(@rspack/core@1.7.3(@swc/helpers@0.5.18))(less@4.5.1):
     dependencies:
     dependencies:
       less: 4.5.1
       less: 4.5.1
     optionalDependencies:
     optionalDependencies:
@@ -14064,11 +14095,13 @@ snapshots:
 
 
   number-to-words@1.2.4: {}
   number-to-words@1.2.4: {}
 
 
-  nunjucks@3.2.4:
+  nunjucks@3.2.4(chokidar@5.0.0):
     dependencies:
     dependencies:
       a-sync-waterfall: 1.0.1
       a-sync-waterfall: 1.0.1
       asap: 2.0.6
       asap: 2.0.6
       commander: 5.1.0
       commander: 5.1.0
+    optionalDependencies:
+      chokidar: 5.0.0
 
 
   oas-kit-common@1.0.8:
   oas-kit-common@1.0.8:
     dependencies:
     dependencies:
@@ -14785,7 +14818,7 @@ snapshots:
 
 
   robust-predicates@3.0.2: {}
   robust-predicates@3.0.2: {}
 
 
-  rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1):
+  rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2):
     dependencies:
     dependencies:
       '@oxc-project/runtime': 0.97.0
       '@oxc-project/runtime': 0.97.0
       fdir: 6.5.0(picomatch@4.0.3)
       fdir: 6.5.0(picomatch@4.0.3)
@@ -14796,11 +14829,13 @@ snapshots:
       tinyglobby: 0.2.15
       tinyglobby: 0.2.15
     optionalDependencies:
     optionalDependencies:
       '@types/node': 24.10.9
       '@types/node': 24.10.9
+      esbuild: 0.27.2
       fsevents: 2.3.3
       fsevents: 2.3.3
       jiti: 2.6.1
       jiti: 2.6.1
       less: 4.5.1
       less: 4.5.1
+      yaml: 1.10.2
 
 
-  rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1):
+  rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2):
     dependencies:
     dependencies:
       '@oxc-project/runtime': 0.97.0
       '@oxc-project/runtime': 0.97.0
       fdir: 6.5.0(picomatch@4.0.3)
       fdir: 6.5.0(picomatch@4.0.3)
@@ -14815,6 +14850,7 @@ snapshots:
       fsevents: 2.3.3
       fsevents: 2.3.3
       jiti: 2.6.1
       jiti: 2.6.1
       less: 4.5.1
       less: 4.5.1
+      yaml: 1.10.2
 
 
   rolldown@1.0.0-beta.50:
   rolldown@1.0.0-beta.50:
     dependencies:
     dependencies:
@@ -15580,9 +15616,9 @@ snapshots:
 
 
   universalify@2.0.1: {}
   universalify@2.0.1: {}
 
 
-  unocss@66.6.0(postcss@5.2.18)(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)):
+  unocss@66.6.0(postcss@5.2.18)(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)):
     dependencies:
     dependencies:
-      '@unocss/astro': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/astro': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
       '@unocss/cli': 66.6.0
       '@unocss/cli': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/postcss': 66.6.0(postcss@5.2.18)
       '@unocss/postcss': 66.6.0(postcss@5.2.18)
@@ -15600,16 +15636,16 @@ snapshots:
       '@unocss/transformer-compile-class': 66.6.0
       '@unocss/transformer-compile-class': 66.6.0
       '@unocss/transformer-directives': 66.6.0
       '@unocss/transformer-directives': 66.6.0
       '@unocss/transformer-variant-group': 66.6.0
       '@unocss/transformer-variant-group': 66.6.0
-      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
     optionalDependencies:
     optionalDependencies:
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
     transitivePeerDependencies:
     transitivePeerDependencies:
       - postcss
       - postcss
       - supports-color
       - supports-color
 
 
-  unocss@66.6.0(postcss@8.5.6)(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)):
+  unocss@66.6.0(postcss@8.5.6)(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)):
     dependencies:
     dependencies:
-      '@unocss/astro': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/astro': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
       '@unocss/cli': 66.6.0
       '@unocss/cli': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/core': 66.6.0
       '@unocss/postcss': 66.6.0(postcss@8.5.6)
       '@unocss/postcss': 66.6.0(postcss@8.5.6)
@@ -15627,9 +15663,9 @@ snapshots:
       '@unocss/transformer-compile-class': 66.6.0
       '@unocss/transformer-compile-class': 66.6.0
       '@unocss/transformer-directives': 66.6.0
       '@unocss/transformer-directives': 66.6.0
       '@unocss/transformer-variant-group': 66.6.0
       '@unocss/transformer-variant-group': 66.6.0
-      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1))
+      '@unocss/vite': 66.6.0(rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2))
     optionalDependencies:
     optionalDependencies:
-      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
     transitivePeerDependencies:
     transitivePeerDependencies:
       - postcss
       - postcss
       - supports-color
       - supports-color
@@ -15762,7 +15798,7 @@ snapshots:
     dependencies:
     dependencies:
       monaco-editor: 0.55.1
       monaco-editor: 0.55.1
 
 
-  vite-plugin-svg-icons@2.0.1(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)):
+  vite-plugin-svg-icons@2.0.1(rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)):
     dependencies:
     dependencies:
       '@types/svgo': 2.6.4
       '@types/svgo': 2.6.4
       cors: 2.8.6
       cors: 2.8.6
@@ -15772,7 +15808,7 @@ snapshots:
       pathe: 0.2.0
       pathe: 0.2.0
       svg-baker: 1.7.0
       svg-baker: 1.7.0
       svgo: 2.8.0
       svgo: 2.8.0
-      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)
+      vite: rolldown-vite@7.2.5(@types/node@25.1.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(yaml@1.10.2)
     transitivePeerDependencies:
     transitivePeerDependencies:
       - supports-color
       - supports-color