refactor(rtvi): clarify UI message names
This commit is contained in:
@@ -33,28 +33,26 @@ class RTVIUICommandFrame(SystemFrame):
|
||||
"""A frame for sending a UI command to the client.
|
||||
|
||||
Pipeline-side counterpart of the ``ui-command`` RTVI message.
|
||||
The observer wraps the ``command_name`` + ``payload`` into a
|
||||
The observer wraps the ``command`` + ``payload`` into a
|
||||
``UICommandMessage`` envelope before pushing it to the transport,
|
||||
so the wire shape is:
|
||||
``{label, type: "ui-command", data: {name, payload}}``.
|
||||
``{label, type: "ui-command", data: {command, payload}}``.
|
||||
|
||||
Parameters:
|
||||
command_name: App-defined command name (e.g. ``"toast"``,
|
||||
``"navigate"``, or any app-specific name). The wire
|
||||
field is ``data.name``; this avoids shadowing
|
||||
``SystemFrame.name`` (the per-instance debug label).
|
||||
command: App-defined command (e.g. ``"toast"``,
|
||||
``"navigate"``, or any app-specific command).
|
||||
payload: App-defined payload. Pydantic command models
|
||||
(``Toast``, ``Navigate``, ``ScrollTo``, ...) should be
|
||||
converted to a plain dict via ``model_dump()`` before
|
||||
being placed here; an arbitrary dict works as well.
|
||||
"""
|
||||
|
||||
command_name: str = ""
|
||||
command: str = ""
|
||||
payload: Any = None
|
||||
|
||||
def __str__(self):
|
||||
"""String representation of the UI command frame."""
|
||||
return f"{self.name}(command: {self.command_name})"
|
||||
return f"{self.name}(command: {self.command})"
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -97,17 +95,17 @@ class RTVIUIEventFrame(SystemFrame):
|
||||
|
||||
Parameters:
|
||||
msg_id: The RTVI message id, as set by the client.
|
||||
event_name: App-defined event name (the ``data.name`` field).
|
||||
event: App-defined event (the ``data.event`` field).
|
||||
payload: App-defined payload (the ``data.payload`` field).
|
||||
"""
|
||||
|
||||
msg_id: str = ""
|
||||
event_name: str = ""
|
||||
event: str = ""
|
||||
payload: Any = None
|
||||
|
||||
def __str__(self):
|
||||
"""String representation of the UI event frame."""
|
||||
return f"{self.name}(event: {self.event_name})"
|
||||
return f"{self.name}(event: {self.event})"
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -595,11 +595,11 @@ class UIEventData(BaseModel):
|
||||
"""Inner ``data`` for a ``ui-event`` message.
|
||||
|
||||
Parameters:
|
||||
name: App-defined event name.
|
||||
event: App-defined event.
|
||||
payload: App-defined payload, schemaless by design.
|
||||
"""
|
||||
|
||||
name: str
|
||||
event: str
|
||||
payload: Any | None = None
|
||||
|
||||
|
||||
@@ -607,13 +607,13 @@ class UICommandData(BaseModel):
|
||||
"""Inner ``data`` for a ``ui-command`` message.
|
||||
|
||||
Parameters:
|
||||
name: App-defined command name.
|
||||
command: App-defined command.
|
||||
payload: App-defined payload (already a plain dict by the
|
||||
time it lands on the wire). The standard payload models
|
||||
time it lands on the wire). The standard command payload models
|
||||
below produce the right shape via ``model_dump()``.
|
||||
"""
|
||||
|
||||
name: str
|
||||
command: str
|
||||
payload: Any | None = None
|
||||
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ class RTVIObserver(BaseObserver):
|
||||
await self.send_rtvi_message(message)
|
||||
elif isinstance(frame, RTVIUICommandFrame):
|
||||
message = RTVI.UICommandMessage(
|
||||
data=RTVI.UICommandData(name=frame.command_name, payload=frame.payload)
|
||||
data=RTVI.UICommandData(command=frame.command, payload=frame.payload)
|
||||
)
|
||||
await self.send_rtvi_message(message)
|
||||
elif isinstance(frame, RTVIUITaskFrame):
|
||||
|
||||
@@ -299,7 +299,7 @@ class RTVIProcessor(FrameProcessor):
|
||||
await self.push_frame(
|
||||
RTVIUIEventFrame(
|
||||
msg_id=message.id,
|
||||
event_name=event_data.name,
|
||||
event=event_data.event,
|
||||
payload=event_data.payload,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -14,6 +14,10 @@ with existing client code, and we want a test that fails loudly.
|
||||
|
||||
import unittest
|
||||
|
||||
from pipecat.processors.frameworks.rtvi.frames import (
|
||||
RTVIUICommandFrame,
|
||||
RTVIUIEventFrame,
|
||||
)
|
||||
from pipecat.processors.frameworks.rtvi.models import (
|
||||
Click,
|
||||
Focus,
|
||||
@@ -43,27 +47,27 @@ class TestEnvelopeMessages(unittest.TestCase):
|
||||
"""Pin the on-the-wire envelope shapes for each first-class UI message."""
|
||||
|
||||
def test_ui_event_envelope(self):
|
||||
msg = UIEventMessage(id="m1", data=UIEventData(name="nav_click", payload={"view": "home"}))
|
||||
msg = UIEventMessage(id="m1", data=UIEventData(event="nav_click", payload={"view": "home"}))
|
||||
self.assertEqual(
|
||||
msg.model_dump(),
|
||||
{
|
||||
"label": "rtvi-ai",
|
||||
"type": "ui-event",
|
||||
"id": "m1",
|
||||
"data": {"name": "nav_click", "payload": {"view": "home"}},
|
||||
"data": {"event": "nav_click", "payload": {"view": "home"}},
|
||||
},
|
||||
)
|
||||
|
||||
def test_ui_command_envelope_no_id(self):
|
||||
# Server-to-client push: no id field on the envelope (matches
|
||||
# ServerMessage / LLMFunctionCallMessage shape).
|
||||
msg = UICommandMessage(data=UICommandData(name="toast", payload={"title": "Saved"}))
|
||||
msg = UICommandMessage(data=UICommandData(command="toast", payload={"title": "Saved"}))
|
||||
self.assertEqual(
|
||||
msg.model_dump(),
|
||||
{
|
||||
"label": "rtvi-ai",
|
||||
"type": "ui-command",
|
||||
"data": {"name": "toast", "payload": {"title": "Saved"}},
|
||||
"data": {"command": "toast", "payload": {"title": "Saved"}},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -187,5 +191,20 @@ class TestPayloadShapes(unittest.TestCase):
|
||||
self.assertIsNone(payload["end_offset"])
|
||||
|
||||
|
||||
class TestFrames(unittest.TestCase):
|
||||
"""Pin the frame API for named UI messages."""
|
||||
|
||||
def test_ui_command_frame_names_command_and_payload(self):
|
||||
frame = RTVIUICommandFrame(command="toast", payload={"title": "Saved"})
|
||||
self.assertEqual(frame.command, "toast")
|
||||
self.assertEqual(frame.payload, {"title": "Saved"})
|
||||
|
||||
def test_ui_event_frame_names_event_and_payload(self):
|
||||
frame = RTVIUIEventFrame(msg_id="m1", event="nav_click", payload={"view": "home"})
|
||||
self.assertEqual(frame.msg_id, "m1")
|
||||
self.assertEqual(frame.event, "nav_click")
|
||||
self.assertEqual(frame.payload, {"view": "home"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user