// One decoded step of a provider's stream. What a dialect makes of the bytes
// as they arrive, before there is a whole message to lift.
///|
/// A step of the reply, as the dialect decoded it (pi's
/// `AssistantMessageEvent`).
///
/// `content_index` is the block's position in the assistant message being
/// built — the same index `stream_finish` will hand back as `content[i]` — so
/// a consumer can key a partial render by it without knowing which wire
/// format produced it. Events for different blocks are not guaranteed
/// contiguous: a provider may interleave a tool call's arguments with the
/// text after it, which is exactly why the index is on every event and not
/// implied by order.
///
/// Nothing here mentions a transcript, a message id or a media type. Those
/// belong to whoever is embedding this, and a dialect that had to know them
/// could not be published on its own.
pub(all) enum StreamEvent {
/// The reply has begun and named its model. First event, always.
Start(model~ : String)
TextStart(content_index~ : Int)
TextDelta(content_index~ : Int, delta~ : String)
TextEnd(content_index~ : Int)
ThinkingStart(content_index~ : Int)
ThinkingDelta(content_index~ : Int, delta~ : String)
ThinkingEnd(content_index~ : Int)
ToolCallStart(content_index~ : Int, id~ : String, name~ : String)
/// Arguments arrive as partial JSON TEXT — every provider streams them that
/// way — so a consumer that wants them parsed waits for `stream_finish`.
ToolCallDelta(content_index~ : Int, delta~ : String)
ToolCallEnd(content_index~ : Int)
/// The reply is complete. `stream_finish` still produces the message; this
/// is what a live view draws before it arrives.
Done(stop~ : StopReason, usage~ : Usage?)
/// A provider error, which is data here as everywhere else: the call
/// happened and the answer was a refusal, not an exception.
Error(message~ : String)
} derive(Eq, Debug, ToJson)