diff --git a/apps/application/flow/step_node/tool_lib_node/i_tool_lib_node.py b/apps/application/flow/step_node/tool_lib_node/i_tool_lib_node.py index 07408f1fb..e1d9335ce 100644 --- a/apps/application/flow/step_node/tool_lib_node/i_tool_lib_node.py +++ b/apps/application/flow/step_node/tool_lib_node/i_tool_lib_node.py @@ -41,7 +41,8 @@ class FunctionLibNodeParamsSerializer(serializers.Serializer): class IToolLibNode(INode): type = 'tool-lib-node' - support = [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP] + support = [WorkflowMode.APPLICATION, WorkflowMode.APPLICATION_LOOP, WorkflowMode.KNOWLEDGE, + WorkflowMode.KNOWLEDGE_LOOP] def get_node_params_serializer_class(self) -> Type[serializers.Serializer]: return FunctionLibNodeParamsSerializer diff --git a/apps/application/flow/step_node/tool_lib_node/impl/base_tool_lib_node.py b/apps/application/flow/step_node/tool_lib_node/impl/base_tool_lib_node.py index 15b4ab3ca..160828382 100644 --- a/apps/application/flow/step_node/tool_lib_node/impl/base_tool_lib_node.py +++ b/apps/application/flow/step_node/tool_lib_node/impl/base_tool_lib_node.py @@ -138,7 +138,7 @@ class BaseToolLibNodeNode(IToolLibNode): tool_lib = QuerySet(Tool).filter(id=tool_lib_id).first() valid_function(tool_lib, workspace_id) params = { - field.get('name'): convert_value( + field.get('name'): convert_value( field.get('name'), field.get('value'), field.get('type'), field.get('is_required'), field.get('source'), self @@ -157,8 +157,12 @@ class BaseToolLibNodeNode(IToolLibNode): all_params = init_params_default_value | json.loads(rsa_long_decrypt(tool_lib.init_params)) | params else: all_params = init_params_default_value | params + if self.node.properties.get('kind') == 'data-source': + all_params = {**all_params, **self.workflow_params.get('data_source')} result = function_executor.exec_code(tool_lib.code, all_params) - return NodeResult({'result': result}, {}, _write_context=write_context) + return NodeResult({'result': result}, + (self.workflow_manage.params.get('knowledge_base') or {}) if self.node.properties.get( + 'kind') == 'data-source' else {}, _write_context=write_context) def get_details(self, index: int, **kwargs): return { diff --git a/apps/common/utils/tool_code.py b/apps/common/utils/tool_code.py index 3c9c9af03..f8e819557 100644 --- a/apps/common/utils/tool_code.py +++ b/apps/common/utils/tool_code.py @@ -47,11 +47,12 @@ class ToolExecutor: finally: os.umask(old_mask) - def exec_code(self, code_str, keywords): + def exec_code(self, code_str, keywords, function_name=None): self.validate_banned_keywords(code_str) _id = str(uuid.uuid7()) success = '{"code":200,"msg":"成功","data":exec_result}' err = '{"code":500,"msg":str(e),"data":None}' + action_function = f'({function_name !a}, locals_v.get({function_name !a}))' if function_name else 'locals_v.popitem()' result_path = f'{self.sandbox_path}/result/{_id}.result' python_paths = CONFIG.get_sandbox_python_package_paths().split(',') _exec_code = f""" @@ -66,7 +67,7 @@ try: keywords={keywords} globals_v={'{}'} exec({dedent(code_str)!a}, globals_v, locals_v) - f_name, f = locals_v.popitem() + f_name, f = {action_function} for local in locals_v: globals_v[local] = locals_v[local] exec_result=f(**keywords) diff --git a/apps/knowledge/serializers/knowledge_workflow.py b/apps/knowledge/serializers/knowledge_workflow.py index 04ac6fa82..09e3f94cf 100644 --- a/apps/knowledge/serializers/knowledge_workflow.py +++ b/apps/knowledge/serializers/knowledge_workflow.py @@ -1,5 +1,5 @@ # coding=utf-8 - +import json from typing import Dict import uuid_utils.compat as uuid @@ -13,13 +13,18 @@ from application.flow.i_step_node import KnowledgeWorkflowPostHandler from application.flow.knowledge_workflow_manage import KnowledgeWorkflowManage from application.flow.step_node import get_node from common.exception.app_exception import AppApiException +from common.utils.rsa_util import rsa_long_decrypt +from common.utils.tool_code import ToolExecutor from knowledge.models import KnowledgeScope, Knowledge, KnowledgeType, KnowledgeWorkflow from knowledge.models.knowledge_action import KnowledgeAction, State from knowledge.serializers.knowledge import KnowledgeModelSerializer +from maxkb.const import CONFIG from system_manage.models import AuthTargetType from system_manage.serializers.user_resource_permission import UserResourcePermissionSerializer from tools.models import Tool +tool_executor = ToolExecutor(CONFIG.get('SANDBOX')) + class KnowledgeWorkflowModelSerializer(serializers.ModelSerializer): class Meta: @@ -62,20 +67,22 @@ class KnowledgeWorkflowActionSerializer(serializers.Serializer): class KnowledgeWorkflowSerializer(serializers.Serializer): - class Form(serializers.Serializer): + class Datasource(serializers.Serializer): type = serializers.CharField(required=True, label=_('type')) id = serializers.CharField(required=True, label=_('type')) - node = serializers.DictField(required=True, label="") + params = serializers.DictField(required=True, label="") + function_name = serializers.CharField(required=True, label=_('function_name')) - def get_form_list(self): + def action(self): self.is_valid(raise_exception=True) if self.data.get('type') == 'local': node = get_node(self.data.get('id'), WorkflowMode.KNOWLEDGE) - return node.get_form_list(self.data.get("node")) + return node.__getattribute__(node, self.data.get("function_name"))(**self.data.get("params")) elif self.data.get('type') == 'tool': tool = QuerySet(Tool).filter(id=self.data.get("id")).first() - # todo 调用工具数据源的函数获取表单列表 - return None + init_params = json.loads(rsa_long_decrypt(tool.init_params)) + return tool_executor.exec_code(tool.code, {**init_params, **self.data.get('params')}, + self.data.get('function_name')) class Create(serializers.Serializer): user_id = serializers.UUIDField(required=True, label=_('user id')) diff --git a/apps/knowledge/urls.py b/apps/knowledge/urls.py index 5cbec1b78..f5532f0db 100644 --- a/apps/knowledge/urls.py +++ b/apps/knowledge/urls.py @@ -69,7 +69,8 @@ urlpatterns = [ path('workspace//knowledge//problem//', views.ProblemView.Page.as_view()), path('workspace//knowledge//document//', views.DocumentView.Page.as_view()), path('workspace//knowledge//', views.KnowledgeView.Page.as_view()), - path('workspace//knowledge//form_list//', views.KnowledgeWorkflowFormView.as_view()), + path('workspace//knowledge//datasource///form_list', views.KnowledgeDatasourceFormListView.as_view()), + path('workspace//knowledge//datasource///', views.KnowledgeDatasourceView.as_view()), path('workspace//knowledge//action', views.KnowledgeWorkflowActionView.as_view()), path('workspace//knowledge//action/', views.KnowledgeWorkflowActionView.Operate.as_view()) diff --git a/apps/knowledge/views/knowledge_workflow.py b/apps/knowledge/views/knowledge_workflow.py index f0b0d0c26..548758781 100644 --- a/apps/knowledge/views/knowledge_workflow.py +++ b/apps/knowledge/views/knowledge_workflow.py @@ -15,12 +15,18 @@ from knowledge.serializers.common import get_knowledge_operation_object from knowledge.serializers.knowledge_workflow import KnowledgeWorkflowSerializer, KnowledgeWorkflowActionSerializer -class KnowledgeWorkflowFormView(APIView): +class KnowledgeDatasourceFormListView(APIView): authentication_classes = [TokenAuth] def post(self, request: Request, workspace_id: str, knowledge_id: str, type: str, id: str): - return result.success(KnowledgeWorkflowSerializer.Form( - data={'type': type, 'id': id, 'node': request.data.get('node')}).get_form_list()) + return result.success(KnowledgeWorkflowSerializer.Datasource( + data={'type': type, 'id': id, 'params': request.data, 'function_name': 'get_form_list'}).action()) + + +class KnowledgeDatasourceView(APIView): + def post(self, request: Request, workspace_id: str, knowledge_id: str, type: str, id: str, function_name: str): + return result.success(KnowledgeWorkflowSerializer.Datasource( + data={'type': type, 'id': id, 'params': request.data, 'function_name': function_name}).action()) class KnowledgeWorkflowActionView(APIView): diff --git a/ui/src/api/knowledge/knowledge.ts b/ui/src/api/knowledge/knowledge.ts index 22ad4995b..bf07d11c1 100644 --- a/ui/src/api/knowledge/knowledge.ts +++ b/ui/src/api/knowledge/knowledge.ts @@ -328,7 +328,34 @@ const getKnowledgeWorkflowFormList: ( node, loading, ) => { - return post(`${prefix.value}/${knowledge_id}/form_list/${type}/${id}`, { node }, {}, loading) + return post( + `${prefix.value}/${knowledge_id}/datasource/${type}/${id}/form_list`, + { node }, + {}, + loading, + ) +} +const getKnowledgeWorkflowDatasourceDetails: ( + knowledge_id: string, + type: 'loacl' | 'tool', + id: string, + params: any, + function_name: string, + loading?: Ref, +) => Promise> = ( + knowledge_id: string, + type: 'loacl' | 'tool', + id: string, + params, + function_name, + loading, +) => { + return post( + `${prefix.value}/${knowledge_id}/datasource/${type}/${id}/${function_name}`, + params, + {}, + loading, + ) } const workflowAction: ( knowledge_id: string, @@ -371,4 +398,5 @@ export default { getKnowledgeWorkflowFormList, workflowAction, getWorkflowAction, + getKnowledgeWorkflowDatasourceDetails, } diff --git a/ui/src/components/dynamics-form/Demo.vue b/ui/src/components/dynamics-form/Demo.vue index 5e631f3de..c572928f3 100644 --- a/ui/src/components/dynamics-form/Demo.vue +++ b/ui/src/components/dynamics-form/Demo.vue @@ -22,6 +22,15 @@ import { ref } from 'vue' import type { Dict } from '@/api/type/common' const damo_data: Array = [ + { + field: 'aaa', + input_type: 'Tree', + attrs: { + lazy: true, + url: '/workspace/${current_workspace_id}/knowledge/${current_knowledge_id}/datasource/tool/019aa0bb-552d-73a3-b0c6-1809eaedb139/get_file_list', + }, + label: '', + }, { field: 'aa', input_type: 'LocalFileUpload', diff --git a/ui/src/components/dynamics-form/items/tree/Tree.vue b/ui/src/components/dynamics-form/items/tree/Tree.vue new file mode 100644 index 000000000..15dd43474 --- /dev/null +++ b/ui/src/components/dynamics-form/items/tree/Tree.vue @@ -0,0 +1,222 @@ + + + diff --git a/ui/src/views/knowledge-workflow/component/DropdownMenu.vue b/ui/src/views/knowledge-workflow/component/DropdownMenu.vue index 6706a612f..7fd512ce5 100644 --- a/ui/src/views/knowledge-workflow/component/DropdownMenu.vue +++ b/ui/src/views/knowledge-workflow/component/DropdownMenu.vue @@ -72,7 +72,7 @@ - +