From bb4fecf3d180f587bf4371fa37deb0ebd7015779 Mon Sep 17 00:00:00 2001 From: Novice <857526207@qq.com> Date: Thu, 27 Feb 2025 16:09:13 +0800 Subject: [PATCH 1/3] fix(agent node): tool setting and workflow tool. (#14461) --- api/core/workflow/nodes/agent/agent_node.py | 49 ++++++++++++++++++--- api/core/workflow/nodes/agent/entities.py | 6 +++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py index db846249612b56..d50c858fff1497 100644 --- a/api/core/workflow/nodes/agent/agent_node.py +++ b/api/core/workflow/nodes/agent/agent_node.py @@ -8,12 +8,12 @@ from core.model_runtime.entities.model_entities import ModelType from core.plugin.manager.exc import PluginDaemonClientSideError from core.plugin.manager.plugin import PluginInstallationManager -from core.tools.entities.tool_entities import ToolProviderType +from core.tools.entities.tool_entities import ToolParameter, ToolProviderType from core.tools.tool_manager import ToolManager from core.workflow.entities.node_entities import NodeRunResult from core.workflow.entities.variable_pool import VariablePool from core.workflow.enums import SystemVariableKey -from core.workflow.nodes.agent.entities import AgentNodeData +from core.workflow.nodes.agent.entities import AgentNodeData, ParamsAutoGenerated from core.workflow.nodes.base.entities import BaseNodeData from core.workflow.nodes.enums import NodeType from core.workflow.nodes.event.event import RunCompletedEvent @@ -156,16 +156,38 @@ def _generate_agent_parameters( value = cast(list[dict[str, Any]], value) value = [tool for tool in value if tool.get("enabled", False)] + for tool in value: + if "schemas" in tool: + tool.pop("schemas") + parameters = tool.get("parameters", {}) + if all(isinstance(v, dict) for _, v in parameters.items()): + params = {} + for key, param in parameters.items(): + if param.get("auto", ParamsAutoGenerated.OPEN.value) == ParamsAutoGenerated.CLOSE.value: + value_param = param.get("value", {}) + params[key] = value_param.get("value", "") if value_param is not None else None + else: + params[key] = None + parameters = params + tool["settings"] = {k: v.get("value", None) for k, v in tool.get("settings", {}).items()} + tool["parameters"] = parameters + if not for_log: if parameter.type == "array[tools]": value = cast(list[dict[str, Any]], value) tool_value = [] for tool in value: + provider_type = ToolProviderType(tool.get("type", ToolProviderType.BUILT_IN.value)) + setting_params = tool.get("settings", {}) + parameters = tool.get("parameters", {}) + manual_input_params = [key for key, value in parameters.items() if value is not None] + + parameters = {**parameters, **setting_params} entity = AgentToolEntity( provider_id=tool.get("provider_name", ""), - provider_type=ToolProviderType.BUILT_IN, + provider_type=provider_type, tool_name=tool.get("tool_name", ""), - tool_parameters=tool.get("parameters", {}), + tool_parameters=parameters, plugin_unique_identifier=tool.get("plugin_unique_identifier", None), ) @@ -178,11 +200,26 @@ def _generate_agent_parameters( tool_runtime.entity.description.llm = ( extra.get("descrption", "") or tool_runtime.entity.description.llm ) - + for tool_runtime_params in tool_runtime.entity.parameters: + tool_runtime_params.form = ( + ToolParameter.ToolParameterForm.FORM + if tool_runtime_params.name in manual_input_params + else tool_runtime_params.form + ) + manual_input_value = {} + if tool_runtime.entity.parameters: + manual_input_value = { + key: value for key, value in parameters.items() if key in manual_input_params + } + runtime_parameters = { + **tool_runtime.runtime.runtime_parameters, + **manual_input_value, + } tool_value.append( { **tool_runtime.entity.model_dump(mode="json"), - "runtime_parameters": tool_runtime.runtime.runtime_parameters, + "runtime_parameters": runtime_parameters, + "provider_type": provider_type.value, } ) value = tool_value diff --git a/api/core/workflow/nodes/agent/entities.py b/api/core/workflow/nodes/agent/entities.py index 066dcd5666ea85..a10cee69bdf2a6 100644 --- a/api/core/workflow/nodes/agent/entities.py +++ b/api/core/workflow/nodes/agent/entities.py @@ -1,3 +1,4 @@ +from enum import Enum from typing import Any, Literal, Union from pydantic import BaseModel @@ -16,3 +17,8 @@ class AgentInput(BaseModel): type: Literal["mixed", "variable", "constant"] agent_parameters: dict[str, AgentInput] + + +class ParamsAutoGenerated(Enum): + CLOSE = 0 + OPEN = 1 From ddf9eb1f9a69be1acf1ee8470d32f68b1495e1ce Mon Sep 17 00:00:00 2001 From: NFish Date: Thu, 27 Feb 2025 16:54:54 +0800 Subject: [PATCH 2/3] fix: page broke down while rendering node contained img and other elements (#14467) --- web/app/components/base/markdown.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/app/components/base/markdown.tsx b/web/app/components/base/markdown.tsx index 1a4358c8bcf712..2b58b932a479f7 100644 --- a/web/app/components/base/markdown.tsx +++ b/web/app/components/base/markdown.tsx @@ -211,7 +211,9 @@ const Paragraph = (paragraph: any) => { return ( <> -

{paragraph.children.slice(1)}

+ { + Array.isArray(paragraph.children) ?

{paragraph.children.slice(1)}

: null + } ) } From 002b16e1c6ada0fbb3bb0f82f2ff13d3d7b48733 Mon Sep 17 00:00:00 2001 From: QuantumGhost Date: Thu, 27 Feb 2025 18:59:07 +0800 Subject: [PATCH 3/3] fix: properly escape `collectionName` in query string parameters (#14476) --- web/service/_tools_util.spec.ts | 16 ++++++++++++++++ web/service/_tools_util.ts | 5 +++++ web/service/tools.ts | 10 +++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 web/service/_tools_util.spec.ts create mode 100644 web/service/_tools_util.ts diff --git a/web/service/_tools_util.spec.ts b/web/service/_tools_util.spec.ts new file mode 100644 index 00000000000000..f06e5a1e344d3b --- /dev/null +++ b/web/service/_tools_util.spec.ts @@ -0,0 +1,16 @@ +import { buildProviderQuery } from './_tools_util' + +describe('makeProviderQuery', () => { + test('collectionName without special chars', () => { + expect(buildProviderQuery('ABC')).toBe('provider=ABC') + }) + test('should escape &', () => { + expect(buildProviderQuery('ABC&DEF')).toBe('provider=ABC%26DEF') + }) + test('should escape /', () => { + expect(buildProviderQuery('ABC/DEF')).toBe('provider=ABC%2FDEF') + }) + test('should escape ?', () => { + expect(buildProviderQuery('ABC?DEF')).toBe('provider=ABC%3FDEF') + }) +}) diff --git a/web/service/_tools_util.ts b/web/service/_tools_util.ts new file mode 100644 index 00000000000000..89dede8163f4c6 --- /dev/null +++ b/web/service/_tools_util.ts @@ -0,0 +1,5 @@ +export const buildProviderQuery = (collectionName: string): string => { + const query = new URLSearchParams() + query.set('provider', collectionName) + return query.toString() +} diff --git a/web/service/tools.ts b/web/service/tools.ts index d6b2f2034b6f30..38dcf382e6b3f6 100644 --- a/web/service/tools.ts +++ b/web/service/tools.ts @@ -10,6 +10,7 @@ import type { } from '@/app/components/tools/types' import type { ToolWithProvider } from '@/app/components/workflow/types' import type { Label } from '@/app/components/tools/labels/constant' +import { buildProviderQuery } from './_tools_util' export const fetchCollectionList = () => { return get('/workspaces/current/tool-providers') @@ -24,11 +25,13 @@ export const fetchBuiltInToolList = (collectionName: string) => { } export const fetchCustomToolList = (collectionName: string) => { - return get(`/workspaces/current/tool-provider/api/tools?provider=${collectionName}`) + const query = buildProviderQuery(collectionName) + return get(`/workspaces/current/tool-provider/api/tools?${query}`) } export const fetchModelToolList = (collectionName: string) => { - return get(`/workspaces/current/tool-provider/model/tools?provider=${collectionName}`) + const query = buildProviderQuery(collectionName) + return get(`/workspaces/current/tool-provider/model/tools?${query}`) } export const fetchWorkflowToolList = (appID: string) => { @@ -65,7 +68,8 @@ export const parseParamsSchema = (schema: string) => { } export const fetchCustomCollection = (collectionName: string) => { - return get(`/workspaces/current/tool-provider/api/get?provider=${collectionName}`) + const query = buildProviderQuery(collectionName) + return get(`/workspaces/current/tool-provider/api/get?${query}`) } export const createCustomCollection = (collection: CustomCollectionBackend) => {