diff --git a/api/controllers/console/workspace/plugin.py b/api/controllers/console/workspace/plugin.py index 6c2bdb4154..c0a4734828 100644 --- a/api/controllers/console/workspace/plugin.py +++ b/api/controllers/console/workspace/plugin.py @@ -518,15 +518,18 @@ class PluginFetchDynamicSelectOptionsApi(Resource): parser.add_argument("provider_type", type=str, required=True, location="args") args = parser.parse_args() - options = PluginParameterService.get_dynamic_select_options( - tenant_id, - user_id, - args["plugin_id"], - args["provider"], - args["action"], - args["parameter"], - args["provider_type"], - ) + try: + options = PluginParameterService.get_dynamic_select_options( + tenant_id, + user_id, + args["plugin_id"], + args["provider"], + args["action"], + args["parameter"], + args["provider_type"], + ) + except PluginDaemonClientSideError as e: + raise ValueError(e) return jsonable_encoder({"options": options}) diff --git a/api/core/plugin/entities/plugin_daemon.py b/api/core/plugin/entities/plugin_daemon.py index e0d2857e97..592b42c0da 100644 --- a/api/core/plugin/entities/plugin_daemon.py +++ b/api/core/plugin/entities/plugin_daemon.py @@ -1,4 +1,4 @@ -from collections.abc import Mapping +from collections.abc import Mapping, Sequence from datetime import datetime from enum import StrEnum from typing import Any, Generic, Optional, TypeVar @@ -9,6 +9,7 @@ from core.agent.plugin_entities import AgentProviderEntityWithPlugin from core.model_runtime.entities.model_entities import AIModelEntity from core.model_runtime.entities.provider_entities import ProviderEntity from core.plugin.entities.base import BasePluginEntity +from core.plugin.entities.parameters import PluginParameterOption from core.plugin.entities.plugin import PluginDeclaration, PluginEntity from core.tools.entities.common_entities import I18nObject from core.tools.entities.tool_entities import ToolProviderEntityWithPlugin @@ -186,3 +187,7 @@ class PluginOAuthCredentialsResponse(BaseModel): class PluginListResponse(BaseModel): list: list[PluginEntity] total: int + + +class PluginDynamicSelectOptionsResponse(BaseModel): + options: Sequence[PluginParameterOption] = Field(description="The options of the dynamic select.") diff --git a/api/core/plugin/impl/dynamic_select.py b/api/core/plugin/impl/dynamic_select.py index 7ede68f673..f4fb051ee1 100644 --- a/api/core/plugin/impl/dynamic_select.py +++ b/api/core/plugin/impl/dynamic_select.py @@ -1,7 +1,8 @@ -from collections.abc import Mapping, Sequence +from collections.abc import Mapping from typing import Any -from core.plugin.entities.parameters import PluginParameterOption +from core.plugin.entities.plugin import GenericProviderID +from core.plugin.entities.plugin_daemon import PluginDynamicSelectOptionsResponse from core.plugin.impl.base import BasePluginClient @@ -15,18 +16,18 @@ class DynamicSelectClient(BasePluginClient): action: str, credentials: Mapping[str, Any], parameter: str, - ) -> Sequence[PluginParameterOption]: + ) -> PluginDynamicSelectOptionsResponse: """ Fetch dynamic select options for a plugin parameter. """ - return self._request_with_plugin_daemon_response( + response = self._request_with_plugin_daemon_response_stream( "POST", f"plugin/{tenant_id}/dispatch/dynamic_select/fetch_parameter_options", - list[PluginParameterOption], + PluginDynamicSelectOptionsResponse, data={ "user_id": user_id, "data": { - "provider": provider, + "provider": GenericProviderID(provider).provider_name, "credentials": credentials, "provider_action": action, "parameter": parameter, @@ -37,3 +38,8 @@ class DynamicSelectClient(BasePluginClient): "Content-Type": "application/json", }, ) + + for options in response: + return options + + raise ValueError("Plugin service returned no options") diff --git a/api/services/plugin/plugin_parameter_service.py b/api/services/plugin/plugin_parameter_service.py index 9036872e04..393213c0e2 100644 --- a/api/services/plugin/plugin_parameter_service.py +++ b/api/services/plugin/plugin_parameter_service.py @@ -36,21 +36,6 @@ class PluginParameterService: match provider_type: case "tool": - # fetch credentials from db - with Session(db.engine) as session: - db_record = ( - session.query(BuiltinToolProvider) - .filter( - BuiltinToolProvider.tenant_id == tenant_id, - BuiltinToolProvider.provider == provider, - ) - .first() - ) - - if db_record is None: - raise ValueError(f"Builtin provider {provider} not found when fetching credentials") - - credentials = db_record.credentials provider_controller = ToolManager.get_builtin_provider(provider, tenant_id) # init tool configuration tool_configuration = ProviderConfigEncrypter( @@ -60,10 +45,30 @@ class PluginParameterService: provider_identity=provider_controller.entity.identity.name, ) - credentials = tool_configuration.decrypt(credentials) + # check if credentials are required + if not provider_controller.need_credentials: + credentials = {} + else: + # fetch credentials from db + with Session(db.engine) as session: + db_record = ( + session.query(BuiltinToolProvider) + .filter( + BuiltinToolProvider.tenant_id == tenant_id, + BuiltinToolProvider.provider == provider, + ) + .first() + ) + + if db_record is None: + raise ValueError(f"Builtin provider {provider} not found when fetching credentials") + + credentials = tool_configuration.decrypt(db_record.credentials) case _: raise ValueError(f"Invalid provider type: {provider_type}") - return DynamicSelectClient().fetch_dynamic_select_options( - tenant_id, user_id, plugin_id, provider, action, credentials, parameter + return ( + DynamicSelectClient() + .fetch_dynamic_select_options(tenant_id, user_id, plugin_id, provider, action, credentials, parameter) + .options )