"""core/protocols.py 单元测试 — 验证 Protocol 可 runtime_checkable。""" from __future__ import annotations from pathlib import Path from typing import Any import pytest from core.protocols import LLMProvider, TelemetryRecorder, VLMProvider from core.types import LLMResponse class _FakeLLM: async def chat( self, messages: list[dict[str, Any]], *, session_id: str | None = None, parent_call_id: str | None = None, ) -> LLMResponse: return LLMResponse( content="ok", thinking="", model="m", provider="p", prompt_tokens=1, completion_tokens=1, latency_ms=1, ttft_ms=None, max_inter_token_ms=None, cache_hit=False, call_id="c", ) class _FakeVLM: async def chat_with_images( self, messages: list[dict[str, Any]], images: list[str | Path], *, session_id: str | None = None, parent_call_id: str | None = None, ) -> LLMResponse: return LLMResponse( content="ok", thinking="", model="m", provider="p", prompt_tokens=1, completion_tokens=1, latency_ms=1, ttft_ms=None, max_inter_token_ms=None, cache_hit=False, call_id="c", ) class _FakeTelemetry: async def record_llm_call( self, *, call_id: str, parent_call_id: str | None, session_id: str | None, model_name: str, provider: str, messages: str, response: str, thinking: str, prompt_tokens: int, completion_tokens: int, latency_ms: int, ttft_ms: float | None, max_inter_token_ms: float | None, cache_hit: bool, error: str | None, ) -> None: pass def test_fake_llm_satisfies_protocol() -> None: assert isinstance(_FakeLLM(), LLMProvider) def test_fake_vlm_satisfies_protocol() -> None: assert isinstance(_FakeVLM(), VLMProvider) def test_fake_telemetry_satisfies_protocol() -> None: assert isinstance(_FakeTelemetry(), TelemetryRecorder) def test_plain_object_does_not_satisfy() -> None: assert not isinstance(object(), LLMProvider) assert not isinstance(object(), VLMProvider) assert not isinstance(object(), TelemetryRecorder)