| """统一中间表示(IR)—— 2api 框架的核心数据契约。 |
| |
| 上游适配器(``app/upstream/parser.py``)把目标网站的任意原生事件归一成 :class:`IREvent`, |
| 三家 API adapter(``app/adapters/*``)各自消费同一份 IREvent 流,转成 OpenAI / Anthropic 格式。 |
| |
| 换上游时**唯一必改**的是 parser(原生事件 → IREvent);IREvent 本身是稳定契约,勿轻改。 |
| 新增需求优先扩 :attr:`ToolEvent.detail`,而非加 IREvent 字段。 |
| """ |
| from __future__ import annotations |
|
|
| from dataclasses import dataclass, field |
| from typing import Any, Literal |
|
|
| IRKind = Literal["text", "thinking", "tool", "finish", "error"] |
|
|
|
|
| @dataclass |
| class ToolEvent: |
| """工具调用 / 工具事件:agent 内置工具的展示,或 prompt 模式解析出的调用。""" |
|
|
| name: str |
| title: str = "" |
| detail: dict[str, Any] = field(default_factory=dict) |
|
|
|
|
| @dataclass |
| class Usage: |
| """token 用量。优先用上游真实值(parser 填 ``usage_delta``);无则由 :mod:`app.tokens` 估算。""" |
|
|
| input_tokens: int = 0 |
| output_tokens: int = 0 |
| thinking_tokens: int = 0 |
| cached_tokens: int = 0 |
| cache_creation_tokens: int = 0 |
| model: str | None = None |
| provider: str | None = None |
|
|
| def add(self, other: Usage) -> None: |
| self.input_tokens += other.input_tokens |
| self.output_tokens += other.output_tokens |
| self.thinking_tokens += other.thinking_tokens |
| self.cached_tokens += other.cached_tokens |
| self.cache_creation_tokens += other.cache_creation_tokens |
|
|
|
|
| @dataclass |
| class IREvent: |
| """归一后的单个中间事件。adapter 把它转成各家流式格式。""" |
|
|
| kind: IRKind |
| text: str = "" |
| thinking: str = "" |
| tool: ToolEvent | None = None |
| usage_delta: Usage | None = None |
| finish_reason: str | None = None |
| error: str | None = None |
|
|