40 lines
1.2 KiB
Python
40 lines
1.2 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
|
|
|
|
|
|
@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."""
|