2026-03-06 12:02:10 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
from uuid import uuid4
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
from models.agent_chat_message import AgentChatMessageRole
|
2026-03-06 12:02:10 +08:00
|
|
|
from v1.agent.repository import AgentRepository
|
|
|
|
|
|
|
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
class _FakeToolResultStorage:
|
|
|
|
|
def __init__(self, payload: dict[str, object] | None) -> None:
|
|
|
|
|
self._payload = payload
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
async def read_json(self, *, bucket: str, path: str) -> dict[str, object] | None:
|
|
|
|
|
del bucket, path
|
|
|
|
|
return self._payload
|
2026-03-06 12:02:10 +08:00
|
|
|
|
|
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
|
async def test_tool_message_hydrates_content_from_object_storage() -> None:
|
|
|
|
|
repository = AgentRepository(
|
|
|
|
|
session=SimpleNamespace(), # type: ignore[arg-type]
|
|
|
|
|
tool_result_storage=_FakeToolResultStorage(
|
|
|
|
|
{
|
|
|
|
|
"toolName": "front.navigate_to_route",
|
|
|
|
|
"result": {"ok": True, "applied": True, "content": "已跳转"},
|
|
|
|
|
}
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
message = SimpleNamespace(
|
|
|
|
|
id=uuid4(),
|
|
|
|
|
role=AgentChatMessageRole.TOOL,
|
|
|
|
|
created_at=datetime.now(timezone.utc),
|
|
|
|
|
content='{"offloaded":true}',
|
|
|
|
|
metadata_json={
|
|
|
|
|
"tool_call_id": "call-1",
|
|
|
|
|
"storage_bucket": "private",
|
|
|
|
|
"storage_path": "tool-results/run-1/call-1.json",
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
payload = await repository._to_snapshot_message(message) # type: ignore[arg-type]
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
assert payload["toolCallId"] == "call-1"
|
|
|
|
|
assert payload["content"] == "已跳转"
|
2026-03-06 12:02:10 +08:00
|
|
|
|
|
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
@pytest.mark.asyncio
|
|
|
|
|
async def test_tool_message_keeps_inline_content_when_storage_payload_missing() -> None:
|
|
|
|
|
repository = AgentRepository(
|
|
|
|
|
session=SimpleNamespace(), # type: ignore[arg-type]
|
|
|
|
|
tool_result_storage=_FakeToolResultStorage(None),
|
|
|
|
|
)
|
|
|
|
|
message = SimpleNamespace(
|
|
|
|
|
id=uuid4(),
|
|
|
|
|
role=AgentChatMessageRole.TOOL,
|
|
|
|
|
created_at=datetime.now(timezone.utc),
|
|
|
|
|
content="inline-tool-content",
|
|
|
|
|
metadata_json={
|
|
|
|
|
"tool_call_id": "call-2",
|
|
|
|
|
"storage_bucket": "private",
|
|
|
|
|
"storage_path": "tool-results/run-1/call-2.json",
|
|
|
|
|
},
|
|
|
|
|
)
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
payload = await repository._to_snapshot_message(message) # type: ignore[arg-type]
|
2026-03-06 12:02:10 +08:00
|
|
|
|
2026-03-08 17:07:09 +08:00
|
|
|
assert payload["toolCallId"] == "call-2"
|
|
|
|
|
assert payload["content"] == "inline-tool-content"
|