feat: prepare ARR for controlled public deployment
This commit is contained in:
183
tests/test_agent_events.py
Normal file
183
tests/test_agent_events.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from agent_integration.client import OpenAgentEvent
|
||||
from agent_integration.events import AgentStreamNormalizer
|
||||
|
||||
|
||||
class AgentStreamNormalizerTests(unittest.TestCase):
|
||||
def test_live_langgraph_shape_exposes_only_visible_answer(self):
|
||||
normalizer = AgentStreamNormalizer()
|
||||
raw_events = [
|
||||
OpenAgentEvent(
|
||||
event="metadata",
|
||||
data={"run_id": "run-001", "thread_id": "internal-thread"},
|
||||
event_id="1",
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="values",
|
||||
data={
|
||||
"messages": [{"type": "human", "content": "hello"}],
|
||||
"thread_data": {"workspace_path": "/internal/secret/path"},
|
||||
},
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="messages",
|
||||
data=[
|
||||
{
|
||||
"type": "AIMessageChunk",
|
||||
"content": "",
|
||||
"additional_kwargs": {"reasoning_content": "INTERNAL_REASONING"},
|
||||
},
|
||||
{"langgraph_node": "model"},
|
||||
],
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="messages",
|
||||
data=[
|
||||
{"type": "AIMessageChunk", "content": "INTERNAL_TITLE"},
|
||||
{"langgraph_node": "TitleMiddleware.after_model", "tags": ["middleware:title"]},
|
||||
],
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="messages",
|
||||
data=[
|
||||
{"type": "AIMessageChunk", "content": "连接"},
|
||||
{"langgraph_node": "model"},
|
||||
],
|
||||
event_id="2",
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="messages",
|
||||
data=[
|
||||
{"type": "AIMessageChunk", "content": "成功"},
|
||||
{"langgraph_node": "model"},
|
||||
],
|
||||
event_id="3",
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="messages",
|
||||
data=[
|
||||
{
|
||||
"type": "ai",
|
||||
"content": "连接成功",
|
||||
"additional_kwargs": {"reasoning_content": "INTERNAL_REASONING"},
|
||||
},
|
||||
{"langgraph_node": "model"},
|
||||
],
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="values",
|
||||
data={
|
||||
"messages": [
|
||||
{"type": "human", "content": "hello"},
|
||||
{
|
||||
"type": "ai",
|
||||
"content": "连接成功",
|
||||
"additional_kwargs": {"reasoning_content": "INTERNAL_REASONING"},
|
||||
},
|
||||
],
|
||||
"thread_data": {"workspace_path": "/internal/secret/path"},
|
||||
},
|
||||
),
|
||||
OpenAgentEvent(
|
||||
event="error",
|
||||
data={
|
||||
"code": "open_agent_final_content_missing",
|
||||
"message": "Open agent run completed without final content",
|
||||
"retryable": True,
|
||||
"run_id": "run-001",
|
||||
"request_id": "request-001",
|
||||
"internal_trace": "DO_NOT_EXPOSE",
|
||||
},
|
||||
),
|
||||
OpenAgentEvent(event="end", data=None, event_id="4"),
|
||||
]
|
||||
|
||||
public_events = []
|
||||
for event in raw_events:
|
||||
public_events.extend(normalizer.feed(event))
|
||||
public_events.extend(normalizer.finish())
|
||||
|
||||
self.assertEqual(
|
||||
[event.event for event in public_events],
|
||||
[
|
||||
"run.started",
|
||||
"message.delta",
|
||||
"message.delta",
|
||||
"message.completed",
|
||||
"run.warning",
|
||||
"run.end",
|
||||
],
|
||||
)
|
||||
self.assertEqual(public_events[0].data, {"run_id": "run-001"})
|
||||
self.assertEqual(public_events[1].data, {"content": "连接"})
|
||||
self.assertEqual(public_events[2].data, {"content": "成功"})
|
||||
self.assertEqual(
|
||||
public_events[3].data,
|
||||
{"content": "连接成功", "streamed": True},
|
||||
)
|
||||
self.assertEqual(public_events[4].event, "run.warning")
|
||||
self.assertEqual(public_events[5].data["status"], "completed_with_warning")
|
||||
self.assertFalse(normalizer.fatal_error)
|
||||
self.assertEqual(normalizer.final_content, "连接成功")
|
||||
rendered = repr([event.to_dict() for event in public_events])
|
||||
self.assertNotIn("INTERNAL_REASONING", rendered)
|
||||
self.assertNotIn("INTERNAL_TITLE", rendered)
|
||||
self.assertNotIn("secret/path", rendered)
|
||||
self.assertNotIn("DO_NOT_EXPOSE", rendered)
|
||||
|
||||
def test_final_content_missing_without_visible_content_is_fatal(self):
|
||||
normalizer = AgentStreamNormalizer()
|
||||
normalizer.feed(
|
||||
OpenAgentEvent(
|
||||
event="error",
|
||||
data={
|
||||
"code": "open_agent_final_content_missing",
|
||||
"message": "missing",
|
||||
"retryable": True,
|
||||
},
|
||||
)
|
||||
)
|
||||
public_events = normalizer.feed(OpenAgentEvent(event="end", data=None))
|
||||
|
||||
self.assertTrue(normalizer.fatal_error)
|
||||
self.assertEqual([event.event for event in public_events], ["run.error", "run.end"])
|
||||
self.assertEqual(public_events[-1].data["status"], "failed")
|
||||
|
||||
def test_values_final_message_is_fallback_when_no_deltas_arrive(self):
|
||||
normalizer = AgentStreamNormalizer()
|
||||
normalizer.feed(
|
||||
OpenAgentEvent(
|
||||
event="values",
|
||||
data={"messages": [{"type": "ai", "content": "完整答案"}]},
|
||||
)
|
||||
)
|
||||
public_events = normalizer.finish()
|
||||
|
||||
self.assertEqual(public_events[0].event, "message.completed")
|
||||
self.assertEqual(
|
||||
public_events[0].data,
|
||||
{"content": "完整答案", "streamed": False},
|
||||
)
|
||||
self.assertFalse(normalizer.fatal_error)
|
||||
|
||||
def test_documented_message_delta_shape_remains_supported(self):
|
||||
normalizer = AgentStreamNormalizer()
|
||||
public_events = normalizer.feed(
|
||||
OpenAgentEvent(event="message.delta", data={"content": "你"})
|
||||
)
|
||||
normalizer.feed(
|
||||
OpenAgentEvent(event="run.completed", data={"status": "completed"})
|
||||
)
|
||||
public_events.extend(normalizer.finish())
|
||||
|
||||
self.assertEqual(public_events[0].data, {"content": "你"})
|
||||
self.assertEqual(public_events[1].data, {"content": "你", "streamed": True})
|
||||
self.assertEqual(public_events[2].data["status"], "completed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user