# platform/deskclaw/adapters/protocol.py
# ═══════════════════════════════════════════════════════════════
# AgentAdapter Protocol — DeskClaw 的 Agent 接入统一协议
# 所有 Agent 必须实现此接口才能参与测评
# ═══════════════════════════════════════════════════════════════

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import AsyncIterator, Optional, Any
from enum import Enum


class AgentCapability(Enum):
    """Agent 声明的能力标签，用于匹配可执行的测评项"""

    TEXT_GENERATION = "text_generation"
    CODE_EXECUTION = "code_execution"
    TOOL_USE = "tool_use"
    MULTIMODAL = "multimodal"
    DESKTOP_CONTROL = "desktop_control"
    MULTI_TURN = "multi_turn"


@dataclass(frozen=True)
class AgentMessage:
    role: str  # "user" | "assistant" | "system" | "tool_result"
    content: str
    tool_calls: Optional[list] = None  # 结构化工具调用记录
    metadata: Optional[dict] = None  # 延迟、token 数等运维指标


@dataclass(frozen=True)
class AgentResponse:
    messages: list[AgentMessage]  # 完整对话历史
    final_answer: str  # Agent 最终输出
    trace: dict[str, Any]  # 原始 trace（API 调用、工具链、内部推理）
    usage: dict[str, int]  # {"input_tokens": N, "output_tokens": M, "api_calls": K}
    latency_ms: int  # 端到端延迟（毫秒）


class AgentAdapter(ABC):
    """
    所有 Agent 接入 DeskClaw 的统一协议。
    实现此接口即可参与全部测评流程——U 盘式接入，零修改核心。
    """

    @abstractmethod
    def name(self) -> str:
        """Agent 唯一标识符，如 'claude-4.6', 'nanobot-v1', 'nanoclaw-self'"""
        ...

    @abstractmethod
    def capabilities(self) -> set[AgentCapability]:
        """
        声明此 Agent 支持的能力集合。
        调度器仅会将 capability 匹配的测评项分配给此 Agent。
        不满足能力要求的测评项标记为 SKIPPED（不计入评分但明确列出）。
        """
        ...

    @abstractmethod
    async def execute(
        self,
        messages: list[AgentMessage],
        *,
        max_tokens: int = 4096,
        temperature: float = 0.0,
        tools: Optional[list[dict]] = None,
        timeout_s: int = 300,
    ) -> AgentResponse:
        """
        执行一次完整的 Agent 交互。

        Args:
            messages:    输入对话历史（含 system prompt + 测评指令）
            max_tokens:  最大输出 token
            temperature: 采样温度（测评默认 0.0 确保可复现）
            tools:       可用工具定义（JSON Schema 格式）
            timeout_s:   超时秒数，超时后抛出 AgentTimeoutError

        Returns:
            AgentResponse 包含完整 trace 用于后续评分

        Raises:
            AgentTimeoutError:  超时
            AgentQuotaError:    配额耗尽
            AgentProtocolError: 响应格式不合规范
        """
        ...

    @abstractmethod
    def stream(
        self,
        messages: list[AgentMessage],
        **kwargs,
    ) -> AsyncIterator[AgentMessage]:
        """流式输出，用于实时监控面板和 Web Dashboard 的实时展示"""
        ...

    # ── 可选覆写的默认方法 ──

    def max_context_window(self) -> int:
        """上下文窗口大小（token），默认 128K"""
        return 128_000

    def supports_parallel_tool_calls(self) -> bool:
        """是否支持并行工具调用"""
        return False

    def cost_per_1k_tokens(self) -> dict[str, float]:
        """每千 token 成本（美元），用于 Operational 维度评分"""
        return {"input": 0.0, "output": 0.0}
