1"""Internal LLM types: stream events, tool calls, tool results."""23from __future__ import annotations45from dataclasses import dataclass, field6from typing import Any, Literal78StreamEventType = Literal[9 "text_delta", "tool_call_start", "tool_call_delta", "tool_call_end",10 "usage", "done", "error", "reasoning_delta",11]121314@dataclass15class StreamEvent:16 type: StreamEventType17 data: dict[str, Any] = field(default_factory=dict)181920@dataclass21class ToolCallReq:22 id: str23 name: str24 arguments_json: str = ""25 index: int = 02627 def arguments(self) -> dict[str, Any]:28 import json2930 if not self.arguments_json.strip():31 return {}32 try:33 v = json.loads(self.arguments_json)34 return v if isinstance(v, dict) else {}35 except json.JSONDecodeError:36 return {"__invalid_json__": self.arguments_json[:2000]}373839@dataclass40class Artifact:41 type: str # xlsx | image | csv | file | quiz | sources | search42 file_id: str | None = None43 filename: str | None = None44 preview: Any = None45 url: str | None = None4647 def to_dict(self) -> dict[str, Any]:48 return {49 "type": self.type,50 "file_id": self.file_id,51 "filename": self.filename,52 "preview": self.preview,53 "url": self.url,54 }555657@dataclass58class ToolResult:59 content: str # for the model60 artifacts: list[Artifact] = field(default_factory=list)61 meta: dict[str, Any] = field(default_factory=dict)62 payload: dict[str, Any] = field(default_factory=dict) # for the UI card63 error: bool = False6465 def summary(self, limit: int = 240) -> str:66 s = self.meta.get("summary") or self.content67 return s if len(s) <= limit else s[: limit - 1] + "…"686970@dataclass71class Usage:72 input_tokens: int = 073 output_tokens: int = 074 cost_usd: float = 0.075 model: str = ""76 provider: str = ""77 generation_id: str = ""78