|
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) |
|
) |
|
] |
|
|