From d27b808f2dcefbebb6c68848a3e4ba7cdfa132c5 Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Tue, 27 Oct 2026 16:22:33 +0800 Subject: [PATCH] feat: llm nodes --- ui/src/assets/workflow/icon_llm.svg | 5 + .../chat-management/user-groups/index.vue | 5 +- ui/src/views/system/identity/groups/index.vue | 4 +- ui/src/workflow-canvas/WORKFLOW_README.md | 5 + .../workflow-canvas/icons/llm-node-icon.vue | 4 +- .../llm-node/component/ToolFunctionDialog.vue | 213 ---------------- .../llm-node/component/ToolFunctionDrawer.vue | 236 ++++++++++++++++++ .../component/ToolParameterDialog.vue | 75 ++++++ .../nodes/llm-node/component/ToolsSetting.vue | 102 +++++--- 9 files changed, 392 insertions(+), 257 deletions(-) create mode 100644 ui/src/assets/workflow/icon_llm.svg delete mode 100644 ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDialog.vue create mode 100644 ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDrawer.vue create mode 100644 ui/src/workflow-canvas/nodes/llm-node/component/ToolParameterDialog.vue diff --git a/ui/src/assets/workflow/icon_llm.svg b/ui/src/assets/workflow/icon_llm.svg new file mode 100644 index 00000000000..6d1a09a2ac4 --- /dev/null +++ b/ui/src/assets/workflow/icon_llm.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ui/src/views/system/chat-management/user-groups/index.vue b/ui/src/views/system/chat-management/user-groups/index.vue index ee326e3406d..51c8376d362 100644 --- a/ui/src/views/system/chat-management/user-groups/index.vue +++ b/ui/src/views/system/chat-management/user-groups/index.vue @@ -124,8 +124,9 @@ function handleBatchSelectionChange(selection: unknown[]) { } function handleRemoveMembers(member?: ChatUserGroupMember) { - const title = member ? `是否移除成员:${member?.nick_name}?` : `是否移除选中的 ${batchSelectedMembers.value.length} 个成员?` - MsgConfirm(title, '', { confirmButtonText: '移除' }) + const targetName = member ? member.nick_name || member.username : '' + const title = member ? `是否移除用户:${targetName}?` : `是否移除选中的 ${batchSelectedMembers.value.length} 个用户?` + MsgConfirm(title, '成员移除后,通过该用户组继承的资源权限将被回收,请谨慎操作。', { confirmButtonText: '移除' }) .then(() => { membersLoading.value = true const relationIds = batchSelectedMembers.value.map(({ user_group_relation_id }) => user_group_relation_id) diff --git a/ui/src/views/system/identity/groups/index.vue b/ui/src/views/system/identity/groups/index.vue index c66fd638864..0cd4ca8a3bc 100644 --- a/ui/src/views/system/identity/groups/index.vue +++ b/ui/src/views/system/identity/groups/index.vue @@ -159,8 +159,8 @@ function handleRemoveMembers(member?: SystemUserGroupMember) { if (!group || !members.length) return const targetName = member ? member.nick_name || member.username : '' - const title = member ? `是否移除成员:${targetName}?` : `是否移除选中的 ${members.length} 个成员?` - MsgConfirm(title, '', { confirmButtonText: '移除' }) + const title = member ? `是否移除用户:${targetName}?` : `是否移除选中的 ${members.length} 个用户?` + MsgConfirm(title, '成员移除后,通过该用户组继承的资源权限将被回收,请谨慎操作。', { confirmButtonText: '移除' }) .then(() => { return UserGroupsApi.postRemoveSystemUserGroupMembers( selectedWorkspaceId.value, diff --git a/ui/src/workflow-canvas/WORKFLOW_README.md b/ui/src/workflow-canvas/WORKFLOW_README.md index b1ccf1e2756..e2ac4adbe76 100644 --- a/ui/src/workflow-canvas/WORKFLOW_README.md +++ b/ui/src/workflow-canvas/WORKFLOW_README.md @@ -310,6 +310,11 @@ AI 对话、意图识别、问题优化、参数提取、图片理解、视频 #### AI 对话与提示词 +LLM 节点的工具声明由 `llm-node/component/ToolsSetting.vue` 维护,导入、导出收在更多菜单。 +`ToolFunctionDrawer.vue` 编辑工具草稿,支持 JSON 解析和参数表格;参数通过 +`ToolParameterDialog.vue` 编辑,抽屉检查重名后更新草稿,工具提交后才写回节点。 +工具参数沿用 OpenAI 类型名称,不复用工具输入参数的 `int` / `dict` 协议;取消不修改原配置。 + AI 对话节点的 `component/resource-setting` 仅渲染技能卡片内的 MCP、工具、Skills 和智能体分组, 各分组直接在入口使用 `MkCollapse`,普通列表区直接维护,仅选择弹窗独立封装。 工具和 Skills 的添加入口复用 `SelectToolDialog`,智能体入口使用 `SelectApplicationDialog`; diff --git a/ui/src/workflow-canvas/icons/llm-node-icon.vue b/ui/src/workflow-canvas/icons/llm-node-icon.vue index b73cf6b4daa..e9a8e623fed 100644 --- a/ui/src/workflow-canvas/icons/llm-node-icon.vue +++ b/ui/src/workflow-canvas/icons/llm-node-icon.vue @@ -1,6 +1,6 @@ diff --git a/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDialog.vue b/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDialog.vue deleted file mode 100644 index 056bb775d10..00000000000 --- a/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDialog.vue +++ /dev/null @@ -1,213 +0,0 @@ - - - diff --git a/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDrawer.vue b/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDrawer.vue new file mode 100644 index 00000000000..082e89770a4 --- /dev/null +++ b/ui/src/workflow-canvas/nodes/llm-node/component/ToolFunctionDrawer.vue @@ -0,0 +1,236 @@ + + + diff --git a/ui/src/workflow-canvas/nodes/llm-node/component/ToolParameterDialog.vue b/ui/src/workflow-canvas/nodes/llm-node/component/ToolParameterDialog.vue new file mode 100644 index 00000000000..d5002e9d7ac --- /dev/null +++ b/ui/src/workflow-canvas/nodes/llm-node/component/ToolParameterDialog.vue @@ -0,0 +1,75 @@ + + + diff --git a/ui/src/workflow-canvas/nodes/llm-node/component/ToolsSetting.vue b/ui/src/workflow-canvas/nodes/llm-node/component/ToolsSetting.vue index 9c8ec097224..a80433072f2 100644 --- a/ui/src/workflow-canvas/nodes/llm-node/component/ToolsSetting.vue +++ b/ui/src/workflow-canvas/nodes/llm-node/component/ToolsSetting.vue @@ -5,7 +5,7 @@ import NodeCascader from '@/workflow-canvas/component/NodeCascader.vue' import { createAnchorGuard } from '@/workflow-canvas/core/utils' import type { WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node' import { downloadByURL } from '@/utils/common' -import ToolFunctionDialog from './ToolFunctionDialog.vue' +import ToolFunctionDrawer from './ToolFunctionDrawer.vue' import { normalizeTool, type LlmTool, type LlmToolsSetting } from '../types' defineOptions({ name: 'WorkflowLlmToolsSetting' }) @@ -13,7 +13,7 @@ defineOptions({ name: 'WorkflowLlmToolsSetting' }) const props = defineProps<{ nodeModel: WorkflowNodeModel }>() const setting = defineModel({ required: true }) -const toolDialogRef = useTemplateRef>('toolDialogRef') +const toolDrawerRef = useTemplateRef>('toolDrawerRef') const anchorGuard = createAnchorGuard(props.nodeModel) const existingNames = computed(() => setting.value.tools.map((tool) => tool.function.name)) @@ -21,12 +21,16 @@ function updateSetting(value: Partial) { setting.value = { ...setting.value, ...value } } +function handleOpenToolDrawer(tool?: LlmTool, index?: number) { + toolDrawerRef.value?.open(tool, index) +} + function handleToolSubmit(tool: LlmTool, index?: number) { const tools = cloneDeep(setting.value.tools) if (index === undefined) tools.push(tool) else tools[index] = tool updateSetting({ tools }) - toolDialogRef.value?.close() + toolDrawerRef.value?.close() } function handleDeleteTool(index: number) { @@ -38,6 +42,10 @@ const importVisible = ref(false) const importJson = ref('') const importError = ref('') +function handleOpenImport() { + importVisible.value = true +} + function handleImport() { importError.value = '' try { @@ -74,29 +82,40 @@ onBeforeUnmount(() => anchorGuard.reset())