Skip to main content

atomcode_core/stream/
mod.rs

1use crate::tool::ToolCall;
2
3#[derive(Debug, Clone)]
4pub struct TokenUsage {
5    pub prompt_tokens: usize,
6    pub completion_tokens: usize,
7    /// Tokens served from provider's prompt cache (0 if not supported).
8    pub cached_tokens: usize,
9}
10
11#[derive(Debug, Clone)]
12pub enum StreamEvent {
13    Delta(String),
14    /// Reasoning-model thinking content (e.g. MiniMax-M2.7, DeepSeek-R1,
15    /// o1-series). Some OpenAI-compatible gateways route the full response
16    /// here when `content` is empty — `TurnRunner` promotes it to the
17    /// final text on `Done` if `content` ends up empty, which keeps us from
18    /// silently returning 0-token "Nailed it" responses for reasoning models.
19    Reasoning(String),
20    /// One complete Anthropic extended-thinking content block. Emitted at
21    /// `content_block_stop` by claude.rs after both `thinking_delta` and
22    /// `signature_delta` have streamed in for a given block. The runner
23    /// accumulates these into `MessageContent::AssistantWithToolCalls.
24    /// thinking_blocks` so the next request can echo them back verbatim
25    /// (Anthropic 400s otherwise: `The content[].thinking in the thinking
26    /// mode must be passed back to the API`). Atomic per-block (vs
27    /// streaming text + signature separately) keeps the runner from
28    /// having to pair up out-of-order deltas across content blocks.
29    ThinkingBlock {
30        text: String,
31        signature: String,
32    },
33    ToolCallStart {
34        id: String,
35        name: String,
36    },
37    ToolCallDelta(String),
38    ToolCallDone(ToolCall),
39    Usage(TokenUsage),
40    /// Stream finished. `truncated` = true means finish_reason was "length"
41    /// (model hit max_tokens and was cut off, should continue).
42    Done {
43        truncated: bool,
44    },
45    Error(String),
46    /// Non-fatal advisory the provider wants surfaced to the user. Unlike
47    /// `Error`, the stream and the turn continue normally — the warning
48    /// is a heads-up (e.g. "your proxy looks like it's truncating
49    /// input"), not a failure. The runner forwards it to
50    /// `TurnEvent::Warning` so the TUI can render it without aborting.
51    Warning(String),
52}