diff --git a/api/core/plugin/entities/request.py b/api/core/plugin/entities/request.py index ad4f5d8e0f..4b0c697570 100644 --- a/api/core/plugin/entities/request.py +++ b/api/core/plugin/entities/request.py @@ -1,3 +1,4 @@ +import binascii from collections.abc import Mapping from typing import Any, Literal, Optional @@ -15,6 +16,7 @@ from core.model_runtime.entities.message_entities import ( UserPromptMessage, ) from core.model_runtime.entities.model_entities import ModelType +from core.plugin.utils.http_parser import deserialize_response from core.workflow.nodes.parameter_extractor.entities import ( ModelConfig as ParameterExtractorModelConfig, ) @@ -246,17 +248,6 @@ class TriggerInvokeEventResponse(BaseModel): cancelled: Optional[bool] = False -class PluginTriggerDispatchResponse(BaseModel): - """ - Original response from plugin daemon - """ - - user_id: str - events: list[str] - raw_http_response: str - payload: Mapping[str, Any] = Field(default_factory=dict) - - class TriggerSubscriptionResponse(BaseModel): subscription: dict[str, Any] @@ -272,3 +263,11 @@ class TriggerDispatchResponse(BaseModel): payload: Mapping[str, Any] = Field(default_factory=dict) model_config = ConfigDict(protected_namespaces=(), arbitrary_types_allowed=True) + + @field_validator("response", mode="before") + @classmethod + def convert_response(cls, v: str): + try: + return deserialize_response(binascii.unhexlify(v.encode())) + except Exception as e: + raise ValueError("Failed to deserialize response from hex string") from e diff --git a/api/core/plugin/impl/trigger.py b/api/core/plugin/impl/trigger.py index 9cd7a89e73..611ce74907 100644 --- a/api/core/plugin/impl/trigger.py +++ b/api/core/plugin/impl/trigger.py @@ -6,14 +6,13 @@ from flask import Request from core.plugin.entities.plugin_daemon import CredentialType, PluginTriggerProviderEntity from core.plugin.entities.request import ( - PluginTriggerDispatchResponse, TriggerDispatchResponse, TriggerInvokeEventResponse, TriggerSubscriptionResponse, TriggerValidateProviderCredentialsResponse, ) from core.plugin.impl.base import BasePluginClient -from core.plugin.utils.http_parser import deserialize_response, serialize_request +from core.plugin.utils.http_parser import serialize_request from core.trigger.entities.entities import Subscription from models.provider_ids import TriggerProviderID @@ -171,7 +170,7 @@ class PluginTriggerClient(BasePluginClient): response = self._request_with_plugin_daemon_response_stream( method="POST", path=f"plugin/{tenant_id}/dispatch/trigger/dispatch_event", - type_=PluginTriggerDispatchResponse, + type_=TriggerDispatchResponse, data={ "data": { "provider": provider_id.provider_name, @@ -188,12 +187,7 @@ class PluginTriggerClient(BasePluginClient): ) for resp in response: - return TriggerDispatchResponse( - user_id=resp.user_id or "", - events=resp.events, - response=deserialize_response(binascii.unhexlify(resp.raw_http_response.encode())), - payload=resp.payload, - ) + return resp raise ValueError("No response received from plugin daemon for dispatch event") diff --git a/api/tests/unit_tests/models/test_plugin_entities.py b/api/tests/unit_tests/models/test_plugin_entities.py new file mode 100644 index 0000000000..0c61144deb --- /dev/null +++ b/api/tests/unit_tests/models/test_plugin_entities.py @@ -0,0 +1,22 @@ +import binascii +from collections.abc import Mapping +from typing import Any + +from core.plugin.entities.request import TriggerDispatchResponse + + +def test_trigger_dispatch_response(): + raw_http_response = b'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{"message": "Hello, world!"}' + + data: Mapping[str, Any] = { + "user_id": "123", + "events": ["event1", "event2"], + "response": binascii.hexlify(raw_http_response).decode(), + "payload": {"key": "value"}, + } + + response = TriggerDispatchResponse(**data) + + assert response.response.status_code == 200 + assert response.response.headers["Content-Type"] == "application/json" + assert response.response.get_data(as_text=True) == '{"message": "Hello, world!"}'