Spaces:
Runtime error
Runtime error
| """Public response/stream/iteration types for the LLM API. | |
| These used to live in src/utils/clients.py and have been moved here as part | |
| of the migration toward src/llm/ owning all non-embedding LLM orchestration. | |
| """ | |
| from __future__ import annotations | |
| from collections.abc import AsyncIterator, Callable | |
| from dataclasses import dataclass | |
| from typing import Any, Generic, Literal, TypeVar | |
| from anthropic import AsyncAnthropic | |
| from google import genai | |
| from openai import AsyncOpenAI | |
| from pydantic import BaseModel, Field | |
| T = TypeVar("T") | |
| # OpenAI GPT-5 specific reasoning levels. | |
| ReasoningEffortType = ( | |
| Literal["none", "minimal", "low", "medium", "high", "xhigh", "max"] | None | |
| ) | |
| VerbosityType = Literal["low", "medium", "high"] | None | |
| # Raw SDK client union used by the provider-selection layer. | |
| ProviderClient = AsyncAnthropic | AsyncOpenAI | genai.Client | |
| class IterationData: | |
| """Data passed to iteration callbacks after each tool execution loop iteration.""" | |
| iteration: int | |
| """1-indexed iteration number.""" | |
| tool_calls: list[str] | |
| """List of tool names called in this iteration.""" | |
| input_tokens: int | |
| """Input tokens used in this iteration's LLM call.""" | |
| output_tokens: int | |
| """Output tokens generated in this iteration's LLM call.""" | |
| cache_read_tokens: int = 0 | |
| """Tokens read from cache in this iteration.""" | |
| cache_creation_tokens: int = 0 | |
| """Tokens written to cache in this iteration.""" | |
| IterationCallback = Callable[[IterationData], None] | |
| class HonchoLLMCallResponse(BaseModel, Generic[T]): | |
| """Response object for LLM calls. | |
| Note: | |
| Uncached input tokens = input_tokens - cache_read_input_tokens | |
| + cache_creation_input_tokens | |
| (cache_creation costs 25% more, cache_read costs 90% less) | |
| """ | |
| content: T | |
| input_tokens: int = 0 | |
| output_tokens: int | |
| cache_creation_input_tokens: int = 0 | |
| cache_read_input_tokens: int = 0 | |
| finish_reasons: list[str] | |
| tool_calls_made: list[dict[str, Any]] = Field(default_factory=list) | |
| iterations: int = 0 | |
| """Number of LLM calls made in the tool execution loop.""" | |
| thinking_content: str | None = None | |
| # Full thinking blocks with signatures for multi-turn replay (Anthropic only). | |
| thinking_blocks: list[dict[str, Any]] = Field(default_factory=list) | |
| # OpenRouter reasoning_details for Gemini models — must be preserved across turns. | |
| reasoning_details: list[dict[str, Any]] = Field(default_factory=list) | |
| class HonchoLLMCallStreamChunk(BaseModel): | |
| """A single chunk in a streaming LLM response.""" | |
| content: str | |
| is_done: bool = False | |
| finish_reasons: list[str] = Field(default_factory=list) | |
| output_tokens: int | None = None | |
| class StreamingResponseWithMetadata: | |
| """Streaming response wrapper carrying metadata from a completed tool loop. | |
| Lets callers read tool_calls_made / token counts / thinking_content from | |
| the tool-execution phase while still iterating the final streamed answer. | |
| """ | |
| _stream: AsyncIterator[HonchoLLMCallStreamChunk] | |
| tool_calls_made: list[dict[str, Any]] | |
| input_tokens: int | |
| output_tokens: int | |
| cache_creation_input_tokens: int | |
| cache_read_input_tokens: int | |
| thinking_content: str | None | |
| iterations: int | |
| def __init__( | |
| self, | |
| stream: AsyncIterator[HonchoLLMCallStreamChunk], | |
| tool_calls_made: list[dict[str, Any]], | |
| input_tokens: int, | |
| output_tokens: int, | |
| cache_creation_input_tokens: int, | |
| cache_read_input_tokens: int, | |
| thinking_content: str | None = None, | |
| iterations: int = 0, | |
| ): | |
| self._stream = stream | |
| self.tool_calls_made = tool_calls_made | |
| self.input_tokens = input_tokens | |
| self.output_tokens = output_tokens | |
| self.cache_creation_input_tokens = cache_creation_input_tokens | |
| self.cache_read_input_tokens = cache_read_input_tokens | |
| self.thinking_content = thinking_content | |
| self.iterations = iterations | |
| def __aiter__(self) -> AsyncIterator[HonchoLLMCallStreamChunk]: | |
| return self._stream.__aiter__() | |
| async def __anext__(self) -> HonchoLLMCallStreamChunk: | |
| return await self._stream.__anext__() | |
| __all__ = [ | |
| "HonchoLLMCallResponse", | |
| "HonchoLLMCallStreamChunk", | |
| "IterationCallback", | |
| "IterationData", | |
| "ProviderClient", | |
| "ReasoningEffortType", | |
| "StreamingResponseWithMetadata", | |
| "T", | |
| "VerbosityType", | |
| ] | |