feat(agent): complete task4-6 tool result persistence flow
This commit is contained in:
@@ -1,43 +1,72 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import HTTPException
|
||||
from datetime import datetime, timezone
|
||||
from types import SimpleNamespace
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from models.agent_chat_message import AgentChatMessageRole
|
||||
from v1.agent.repository import AgentRepository
|
||||
|
||||
|
||||
class _FakeSession:
|
||||
def __init__(self) -> None:
|
||||
self.added: list[object] = []
|
||||
class _FakeToolResultStorage:
|
||||
def __init__(self, payload: dict[str, object] | None) -> None:
|
||||
self._payload = payload
|
||||
|
||||
def add(self, obj: object) -> None:
|
||||
self.added.append(obj)
|
||||
|
||||
async def flush(self) -> None:
|
||||
return None
|
||||
|
||||
async def refresh(self, _obj: object) -> None:
|
||||
return None
|
||||
async def read_json(self, *, bucket: str, path: str) -> dict[str, object] | None:
|
||||
del bucket, path
|
||||
return self._payload
|
||||
|
||||
|
||||
async def test_create_session_for_user_creates_session_row() -> None:
|
||||
session = _FakeSession()
|
||||
repository = AgentRepository(session=session) # type: ignore[arg-type]
|
||||
|
||||
await repository.create_session_for_user(
|
||||
user_id="00000000-0000-0000-0000-000000000001"
|
||||
@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",
|
||||
},
|
||||
)
|
||||
|
||||
session_row = session.added[0]
|
||||
assert str(getattr(session_row, "user_id")) == "00000000-0000-0000-0000-000000000001"
|
||||
payload = await repository._to_snapshot_message(message) # type: ignore[arg-type]
|
||||
|
||||
assert payload["toolCallId"] == "call-1"
|
||||
assert payload["content"] == "已跳转"
|
||||
|
||||
|
||||
async def test_create_session_for_user_rejects_invalid_uuid() -> None:
|
||||
session = _FakeSession()
|
||||
repository = AgentRepository(session=session) # type: ignore[arg-type]
|
||||
@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",
|
||||
},
|
||||
)
|
||||
|
||||
try:
|
||||
await repository.create_session_for_user(user_id="invalid-uuid")
|
||||
raise AssertionError("expected invalid user_id")
|
||||
except HTTPException as exc:
|
||||
assert exc.status_code == 422
|
||||
assert exc.detail == "Invalid user_id"
|
||||
payload = await repository._to_snapshot_message(message) # type: ignore[arg-type]
|
||||
|
||||
assert payload["toolCallId"] == "call-2"
|
||||
assert payload["content"] == "inline-tool-content"
|
||||
|
||||
Reference in New Issue
Block a user