| import json |
| from collections.abc import Mapping |
| from datetime import datetime |
| from typing import Any, Optional |
|
|
| from sqlalchemy import or_ |
|
|
| from core.model_runtime.utils.encoders import jsonable_encoder |
| from core.tools.entities.api_entities import UserToolProvider |
| from core.tools.provider.workflow_tool_provider import WorkflowToolProviderController |
| from core.tools.tool_label_manager import ToolLabelManager |
| from core.tools.utils.workflow_configuration_sync import WorkflowToolConfigurationUtils |
| from extensions.ext_database import db |
| from models.model import App |
| from models.tools import WorkflowToolProvider |
| from models.workflow import Workflow |
| from services.tools.tools_transform_service import ToolTransformService |
|
|
|
|
| class WorkflowToolManageService: |
| """ |
| Service class for managing workflow tools. |
| """ |
|
|
| @staticmethod |
| def create_workflow_tool( |
| *, |
| user_id: str, |
| tenant_id: str, |
| workflow_app_id: str, |
| name: str, |
| label: str, |
| icon: dict, |
| description: str, |
| parameters: Mapping[str, Any], |
| privacy_policy: str = "", |
| labels: Optional[list[str]] = None, |
| ) -> dict: |
| WorkflowToolConfigurationUtils.check_parameter_configurations(parameters) |
|
|
| |
| existing_workflow_tool_provider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter( |
| WorkflowToolProvider.tenant_id == tenant_id, |
| |
| or_(WorkflowToolProvider.name == name, WorkflowToolProvider.app_id == workflow_app_id), |
| ) |
| .first() |
| ) |
|
|
| if existing_workflow_tool_provider is not None: |
| raise ValueError(f"Tool with name {name} or app_id {workflow_app_id} already exists") |
|
|
| app = db.session.query(App).filter(App.id == workflow_app_id, App.tenant_id == tenant_id).first() |
| if app is None: |
| raise ValueError(f"App {workflow_app_id} not found") |
|
|
| workflow = app.workflow |
| if workflow is None: |
| raise ValueError(f"Workflow not found for app {workflow_app_id}") |
|
|
| workflow_tool_provider = WorkflowToolProvider( |
| tenant_id=tenant_id, |
| user_id=user_id, |
| app_id=workflow_app_id, |
| name=name, |
| label=label, |
| icon=json.dumps(icon), |
| description=description, |
| parameter_configuration=json.dumps(parameters), |
| privacy_policy=privacy_policy, |
| version=workflow.version, |
| ) |
|
|
| try: |
| WorkflowToolProviderController.from_db(workflow_tool_provider) |
| except Exception as e: |
| raise ValueError(str(e)) |
|
|
| db.session.add(workflow_tool_provider) |
| db.session.commit() |
|
|
| return {"result": "success"} |
|
|
| @classmethod |
| def update_workflow_tool( |
| cls, |
| user_id: str, |
| tenant_id: str, |
| workflow_tool_id: str, |
| name: str, |
| label: str, |
| icon: dict, |
| description: str, |
| parameters: list[dict], |
| privacy_policy: str = "", |
| labels: Optional[list[str]] = None, |
| ) -> dict: |
| """ |
| Update a workflow tool. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :param workflow_tool_id: workflow tool id |
| :param name: name |
| :param label: label |
| :param icon: icon |
| :param description: description |
| :param parameters: parameters |
| :param privacy_policy: privacy policy |
| :param labels: labels |
| :return: the updated tool |
| """ |
| WorkflowToolConfigurationUtils.check_parameter_configurations(parameters) |
|
|
| |
| existing_workflow_tool_provider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter( |
| WorkflowToolProvider.tenant_id == tenant_id, |
| WorkflowToolProvider.name == name, |
| WorkflowToolProvider.id != workflow_tool_id, |
| ) |
| .first() |
| ) |
|
|
| if existing_workflow_tool_provider is not None: |
| raise ValueError(f"Tool with name {name} already exists") |
|
|
| workflow_tool_provider: WorkflowToolProvider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter(WorkflowToolProvider.tenant_id == tenant_id, WorkflowToolProvider.id == workflow_tool_id) |
| .first() |
| ) |
|
|
| if workflow_tool_provider is None: |
| raise ValueError(f"Tool {workflow_tool_id} not found") |
|
|
| app: App = ( |
| db.session.query(App).filter(App.id == workflow_tool_provider.app_id, App.tenant_id == tenant_id).first() |
| ) |
|
|
| if app is None: |
| raise ValueError(f"App {workflow_tool_provider.app_id} not found") |
|
|
| workflow: Workflow = app.workflow |
| if workflow is None: |
| raise ValueError(f"Workflow not found for app {workflow_tool_provider.app_id}") |
|
|
| workflow_tool_provider.name = name |
| workflow_tool_provider.label = label |
| workflow_tool_provider.icon = json.dumps(icon) |
| workflow_tool_provider.description = description |
| workflow_tool_provider.parameter_configuration = json.dumps(parameters) |
| workflow_tool_provider.privacy_policy = privacy_policy |
| workflow_tool_provider.version = workflow.version |
| workflow_tool_provider.updated_at = datetime.now() |
|
|
| try: |
| WorkflowToolProviderController.from_db(workflow_tool_provider) |
| except Exception as e: |
| raise ValueError(str(e)) |
|
|
| db.session.add(workflow_tool_provider) |
| db.session.commit() |
|
|
| if labels is not None: |
| ToolLabelManager.update_tool_labels( |
| ToolTransformService.workflow_provider_to_controller(workflow_tool_provider), labels |
| ) |
|
|
| return {"result": "success"} |
|
|
| @classmethod |
| def list_tenant_workflow_tools(cls, user_id: str, tenant_id: str) -> list[UserToolProvider]: |
| """ |
| List workflow tools. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :return: the list of tools |
| """ |
| db_tools = db.session.query(WorkflowToolProvider).filter(WorkflowToolProvider.tenant_id == tenant_id).all() |
|
|
| tools = [] |
| for provider in db_tools: |
| try: |
| tools.append(ToolTransformService.workflow_provider_to_controller(provider)) |
| except: |
| |
| pass |
|
|
| labels = ToolLabelManager.get_tools_labels(tools) |
|
|
| result = [] |
|
|
| for tool in tools: |
| user_tool_provider = ToolTransformService.workflow_provider_to_user_provider( |
| provider_controller=tool, labels=labels.get(tool.provider_id, []) |
| ) |
| ToolTransformService.repack_provider(user_tool_provider) |
| user_tool_provider.tools = [ |
| ToolTransformService.tool_to_user_tool( |
| tool.get_tools(user_id, tenant_id)[0], labels=labels.get(tool.provider_id, []) |
| ) |
| ] |
| result.append(user_tool_provider) |
|
|
| return result |
|
|
| @classmethod |
| def delete_workflow_tool(cls, user_id: str, tenant_id: str, workflow_tool_id: str) -> dict: |
| """ |
| Delete a workflow tool. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :param workflow_app_id: the workflow app id |
| """ |
| db.session.query(WorkflowToolProvider).filter( |
| WorkflowToolProvider.tenant_id == tenant_id, WorkflowToolProvider.id == workflow_tool_id |
| ).delete() |
|
|
| db.session.commit() |
|
|
| return {"result": "success"} |
|
|
| @classmethod |
| def get_workflow_tool_by_tool_id(cls, user_id: str, tenant_id: str, workflow_tool_id: str) -> dict: |
| """ |
| Get a workflow tool. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :param workflow_app_id: the workflow app id |
| :return: the tool |
| """ |
| db_tool: WorkflowToolProvider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter(WorkflowToolProvider.tenant_id == tenant_id, WorkflowToolProvider.id == workflow_tool_id) |
| .first() |
| ) |
|
|
| if db_tool is None: |
| raise ValueError(f"Tool {workflow_tool_id} not found") |
|
|
| workflow_app: App = db.session.query(App).filter(App.id == db_tool.app_id, App.tenant_id == tenant_id).first() |
|
|
| if workflow_app is None: |
| raise ValueError(f"App {db_tool.app_id} not found") |
|
|
| tool = ToolTransformService.workflow_provider_to_controller(db_tool) |
|
|
| return { |
| "name": db_tool.name, |
| "label": db_tool.label, |
| "workflow_tool_id": db_tool.id, |
| "workflow_app_id": db_tool.app_id, |
| "icon": json.loads(db_tool.icon), |
| "description": db_tool.description, |
| "parameters": jsonable_encoder(db_tool.parameter_configurations), |
| "tool": ToolTransformService.tool_to_user_tool( |
| tool.get_tools(user_id, tenant_id)[0], labels=ToolLabelManager.get_tool_labels(tool) |
| ), |
| "synced": workflow_app.workflow.version == db_tool.version, |
| "privacy_policy": db_tool.privacy_policy, |
| } |
|
|
| @classmethod |
| def get_workflow_tool_by_app_id(cls, user_id: str, tenant_id: str, workflow_app_id: str) -> dict: |
| """ |
| Get a workflow tool. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :param workflow_app_id: the workflow app id |
| :return: the tool |
| """ |
| db_tool: WorkflowToolProvider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter(WorkflowToolProvider.tenant_id == tenant_id, WorkflowToolProvider.app_id == workflow_app_id) |
| .first() |
| ) |
|
|
| if db_tool is None: |
| raise ValueError(f"Tool {workflow_app_id} not found") |
|
|
| workflow_app: App = db.session.query(App).filter(App.id == db_tool.app_id, App.tenant_id == tenant_id).first() |
|
|
| if workflow_app is None: |
| raise ValueError(f"App {db_tool.app_id} not found") |
|
|
| tool = ToolTransformService.workflow_provider_to_controller(db_tool) |
|
|
| return { |
| "name": db_tool.name, |
| "label": db_tool.label, |
| "workflow_tool_id": db_tool.id, |
| "workflow_app_id": db_tool.app_id, |
| "icon": json.loads(db_tool.icon), |
| "description": db_tool.description, |
| "parameters": jsonable_encoder(db_tool.parameter_configurations), |
| "tool": ToolTransformService.tool_to_user_tool( |
| tool.get_tools(user_id, tenant_id)[0], labels=ToolLabelManager.get_tool_labels(tool) |
| ), |
| "synced": workflow_app.workflow.version == db_tool.version, |
| "privacy_policy": db_tool.privacy_policy, |
| } |
|
|
| @classmethod |
| def list_single_workflow_tools(cls, user_id: str, tenant_id: str, workflow_tool_id: str) -> list[dict]: |
| """ |
| List workflow tool provider tools. |
| :param user_id: the user id |
| :param tenant_id: the tenant id |
| :param workflow_app_id: the workflow app id |
| :return: the list of tools |
| """ |
| db_tool: WorkflowToolProvider = ( |
| db.session.query(WorkflowToolProvider) |
| .filter(WorkflowToolProvider.tenant_id == tenant_id, WorkflowToolProvider.id == workflow_tool_id) |
| .first() |
| ) |
|
|
| if db_tool is None: |
| raise ValueError(f"Tool {workflow_tool_id} not found") |
|
|
| tool = ToolTransformService.workflow_provider_to_controller(db_tool) |
|
|
| return [ |
| ToolTransformService.tool_to_user_tool( |
| tool.get_tools(user_id, tenant_id)[0], labels=ToolLabelManager.get_tool_labels(tool) |
| ) |
| ] |
|
|