48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
"""Side channel for what a backend learned during one turn.
|
|
|
|
Frontends pass ``capture=TurnCapture()`` through ``Backend.complete``'s
|
|
``**options``. Backends that keep state per conversation (the Claude SDK
|
|
adapter) fill it in after the stream closes; backends that don't
|
|
(anthropic, raycast) drop the kwarg and the frontend falls back to a
|
|
text-only history.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
__all__ = ["TurnCapture", "TurnUsage"]
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class TurnUsage:
|
|
input_tokens: int = 0
|
|
output_tokens: int = 0
|
|
cache_read_tokens: int = 0
|
|
cache_creation_tokens: int = 0
|
|
cost_usd: float | None = None
|
|
duration_ms: int | None = None
|
|
num_turns: int | None = None
|
|
model_usage: dict[str, Any] | None = None
|
|
"""``ResultMessage.model_usage`` verbatim: per-model tokens, cost, web searches."""
|
|
|
|
context_tokens: int = 0
|
|
"""Input of the last API call in the turn (fresh + cached + written to
|
|
cache) - the context size the model actually ran with, what Claude Code
|
|
shows as the context. The token fields above are sums over every API
|
|
call of the turn and grow with the number of tool calls."""
|
|
|
|
|
|
@dataclass
|
|
class TurnCapture:
|
|
synthesized_messages: list[dict[str, Any]] = field(default_factory=list)
|
|
"""The assistant/tool_result cycle of the turn as Anthropic messages."""
|
|
|
|
session_id: str | None = None
|
|
"""Backend session that ran the turn; persist and pass back as ``session_id``."""
|
|
|
|
usage: TurnUsage | None = None
|
|
interrupted: bool = False
|
|
"""The turn was cut by ``interrupt()`` (urgent inject), not by an error."""
|