diff --git a/pyproject.toml b/pyproject.toml index 0f6daed..0f29312 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "fastapi_poe" -version = "0.0.55" +version = "0.0.56" authors = [ { name="Lida Li", email="lli@quora.com" }, { name="Jelle Zijlstra", email="jelle@quora.com" }, diff --git a/src/fastapi_poe/__init__.py b/src/fastapi_poe/__init__.py index 13373fd..a7488a9 100644 --- a/src/fastapi_poe/__init__.py +++ b/src/fastapi_poe/__init__.py @@ -18,6 +18,7 @@ "PartialResponse", "ErrorResponse", "MetaResponse", + "DataResponse", "RequestContext", "ToolDefinition", "ToolCallDefinition", @@ -41,6 +42,7 @@ from .types import ( Attachment, CostItem, + DataResponse, ErrorResponse, MessageFeedback, MetaResponse, diff --git a/src/fastapi_poe/base.py b/src/fastapi_poe/base.py index d3e346c..a369033 100644 --- a/src/fastapi_poe/base.py +++ b/src/fastapi_poe/base.py @@ -33,6 +33,7 @@ AttachmentUploadResponse, ContentType, CostItem, + DataResponse, ErrorResponse, Identifier, MetaResponse, @@ -772,6 +773,10 @@ async def _cost_requests_inner( def text_event(text: str) -> ServerSentEvent: return ServerSentEvent(data=json.dumps({"text": text}), event="text") + @staticmethod + def data_event(metadata: str) -> ServerSentEvent: + return ServerSentEvent(data=json.dumps({"metadata": metadata}), event="data") + @staticmethod def replace_response_event(text: str) -> ServerSentEvent: return ServerSentEvent( @@ -882,6 +887,8 @@ async def handle_query( linkify=event.linkify, suggested_replies=event.suggested_replies, ) + elif isinstance(event, DataResponse): + yield self.data_event(event.metadata) elif event.is_suggested_reply: yield self.suggested_reply_event(event.text) elif event.is_replace_response: diff --git a/src/fastapi_poe/types.py b/src/fastapi_poe/types.py index 0039f06..0914254 100644 --- a/src/fastapi_poe/types.py +++ b/src/fastapi_poe/types.py @@ -80,6 +80,7 @@ class ProtocolMessage(BaseModel): message_id: str = "" feedback: list[MessageFeedback] = Field(default_factory=list) attachments: list[Attachment] = Field(default_factory=list) + metadata: Optional[str] = None class RequestContext(BaseModel): @@ -237,6 +238,23 @@ class AttachmentUploadResponse(BaseModel): attachment_url: Optional[str] +class DataResponse(BaseModel): + """ + + A response that contains arbitrary data to attach to the bot response. + This data can be retrieved in later requests to the bot within the same chat. + Note that only the final DataResponse object in the stream will be attached to the bot response. + + #### Fields: + - `metadata` (`str`): String of data to attach to the bot response. + + """ + + model_config = ConfigDict(extra="forbid") + + metadata: str + + class PartialResponse(BaseModel): """