139 lines
4.5 KiB
Python
139 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from pipecat.frames.frames import (
|
|
InputTransportMessageFrame,
|
|
OutputTransportMessageUrgentFrame,
|
|
)
|
|
from pipecat.processors.frame_processor import FrameDirection
|
|
from services.brains.base import SessionVariableUpdate
|
|
from services.pipecat.processors import (
|
|
SessionUpdateError,
|
|
SessionUpdateProcessor,
|
|
parse_session_update,
|
|
)
|
|
|
|
|
|
class SessionUpdateParserTests(unittest.TestCase):
|
|
def test_parses_declared_primitive_values(self):
|
|
value = parse_session_update(
|
|
{
|
|
"type": "session-update",
|
|
"schema_version": 1,
|
|
"update_id": "update_1",
|
|
"dynamic_variables": {
|
|
"panel_open": True,
|
|
"selected_option": "approve",
|
|
},
|
|
}
|
|
)
|
|
|
|
self.assertIsNotNone(value)
|
|
self.assertEqual(value.update_id, "update_1")
|
|
self.assertEqual(
|
|
value.dynamic_variables,
|
|
{"panel_open": True, "selected_option": "approve"},
|
|
)
|
|
|
|
def test_rejects_empty_or_nested_updates(self):
|
|
with self.assertRaisesRegex(SessionUpdateError, "不能为空"):
|
|
parse_session_update(
|
|
{
|
|
"type": "session-update",
|
|
"schema_version": 1,
|
|
"update_id": "update_empty",
|
|
"dynamic_variables": {},
|
|
}
|
|
)
|
|
with self.assertRaisesRegex(SessionUpdateError, "仅支持"):
|
|
parse_session_update(
|
|
{
|
|
"type": "session-update",
|
|
"schema_version": 1,
|
|
"update_id": "update_nested",
|
|
"dynamic_variables": {"dialog": {"open": True}},
|
|
}
|
|
)
|
|
|
|
|
|
class SessionUpdateProcessorTests(unittest.IsolatedAsyncioTestCase):
|
|
async def test_returns_snapshot_without_starting_a_turn(self):
|
|
calls = []
|
|
|
|
async def apply_update(dynamic_variables):
|
|
calls.append(dynamic_variables)
|
|
return SessionVariableUpdate(
|
|
changed=["panel_open"],
|
|
dynamic_variables={
|
|
"panel_open": True,
|
|
"selected_option": "none",
|
|
},
|
|
)
|
|
|
|
processor = SessionUpdateProcessor(apply_update)
|
|
outbound = []
|
|
|
|
async def push_frame(frame, direction=FrameDirection.DOWNSTREAM):
|
|
outbound.append((frame, direction))
|
|
|
|
processor.push_frame = push_frame
|
|
await processor.process_frame(
|
|
InputTransportMessageFrame(
|
|
message={
|
|
"type": "session-update",
|
|
"schema_version": 1,
|
|
"update_id": "update_accepted",
|
|
"dynamic_variables": {"panel_open": True},
|
|
}
|
|
),
|
|
FrameDirection.DOWNSTREAM,
|
|
)
|
|
|
|
self.assertEqual(calls, [{"panel_open": True}])
|
|
self.assertEqual(len(outbound), 1)
|
|
self.assertIsInstance(outbound[0][0], OutputTransportMessageUrgentFrame)
|
|
self.assertEqual(
|
|
outbound[0][0].message,
|
|
{
|
|
"type": "session-update-result",
|
|
"update_id": "update_accepted",
|
|
"status": "accepted",
|
|
"changed": ["panel_open"],
|
|
"dynamic_variables": {
|
|
"panel_open": True,
|
|
"selected_option": "none",
|
|
},
|
|
},
|
|
)
|
|
|
|
async def test_validation_failure_returns_error(self):
|
|
async def reject_update(_dynamic_variables):
|
|
raise ValueError("动态变量未声明: panel_open")
|
|
|
|
processor = SessionUpdateProcessor(reject_update)
|
|
outbound = []
|
|
|
|
async def push_frame(frame, direction=FrameDirection.DOWNSTREAM):
|
|
outbound.append((frame, direction))
|
|
|
|
processor.push_frame = push_frame
|
|
await processor.process_frame(
|
|
InputTransportMessageFrame(
|
|
message={
|
|
"type": "session-update",
|
|
"schema_version": 1,
|
|
"update_id": "update_rejected",
|
|
"dynamic_variables": {"panel_open": True},
|
|
}
|
|
),
|
|
FrameDirection.DOWNSTREAM,
|
|
)
|
|
|
|
self.assertEqual(outbound[0][0].message["status"], "error")
|
|
self.assertIn("未声明", outbound[0][0].message["message"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|