package model // StreamKind enumerates the kinds of structured events produced while a // completion streams. It mirrors OpenClaw's AssistantMessageEvent segments // (text / thinking / tool_call) plus a tool-execution progress event, so the // frontend can render each segment into its own surface (body, collapsed // thinking block, tool card) rather than accumulating a single opaque token // stream. type StreamKind string const ( // StreamKindTextStart opens the body-text segment. The single text segment // of a response is bracketed by TextStart/TextEnd; deltas fill it. StreamKindTextStart StreamKind = "text_start" // StreamKindTextDelta is one body-text token fragment. StreamKindTextDelta StreamKind = "text_delta" // StreamKindTextEnd closes the body-text segment. StreamKindTextEnd StreamKind = "text_end" // StreamKindThinkingStart opens a chain-of-thought segment (frontend // collapsed block). Reserved: adapters that report reasoning emit it. StreamKindThinkingStart StreamKind = "thinking_start" // StreamKindThinkingDelta is one reasoning token fragment. StreamKindThinkingDelta StreamKind = "thinking_delta" // StreamKindThinkingEnd closes a reasoning segment. StreamKindThinkingEnd StreamKind = "thinking_end" // StreamKindToolCallStart opens a tool invocation's streaming form. StreamKindToolCallStart StreamKind = "tool_call_start" // StreamKindToolCallDelta is a fragment of the tool arguments (e.g. the // incremental input_json of an Anthropic tool_use block). StreamKindToolCallDelta StreamKind = "tool_call_delta" // StreamKindToolCallEnd closes a tool invocation block. StreamKindToolCallEnd StreamKind = "tool_call_end" // StreamKindToolExecutionStart opens the execution of a tool the model // requested (design/04 §1.1: entering execution). It is emitted by the tool // loop, not the model adapter; Phase carries the running label. StreamKindToolExecutionStart StreamKind = "tool_execution_start" // StreamKindToolExecutionUpdate reports intermediate progress or partial // output while a requested tool runs (design/04 §1.1). Multiple frames per // execution are allowed; the wire mapping is defined, and a producer appears // once tools can report mid-execution progress. StreamKindToolExecutionUpdate StreamKind = "tool_execution_update" // StreamKindToolExecutionEnd closes a tool execution with its terminal // phase (done or error). It is emitted by the tool loop after Invoke // returns. StreamKindToolExecutionEnd StreamKind = "tool_execution_end" // StreamKindTurnStart opens an assistant turn at the loop's run boundary // (design/04 §1.1 turn.start). It carries no payload: the frame shell's // session/turn identity brackets the turn on the client. StreamKindTurnStart StreamKind = "turn_start" // StreamKindTurnEnd closes an assistant turn at the loop's run boundary, // however the run settled (final answer, guardrail stop, terminated tool // loop, exhausted rounds or an error). StreamKindTurnEnd StreamKind = "turn_end" ) // 工具执行 phase 标签(design/04 §1.1 细粒度 phase)。取值与 design/19 §1 // 的节点 status 枚举(running/done/error)一致:start/update 帧带 running, // end 帧带 done 或 error,前端与实时流程图据此驱动工具节点的状态。 const ( // ToolPhaseRunning 标记工具进入执行或仍在执行中。 ToolPhaseRunning = "running" // ToolPhaseDone 标记工具执行成功结束。 ToolPhaseDone = "done" // ToolPhaseError 标记工具执行失败结束。 ToolPhaseError = "error" ) // StreamEvent is a single structured event in a streamed completion. It replaces // the former plain text delta as the unit delivered by Adapter.ChatStream, so a // consumer can distinguish body text from tool calls (and, in time, reasoning // segments) and track each by Index/ID. type StreamEvent struct { // Kind classifies the event (see StreamKind). Kind StreamKind // Delta carries the incremental payload: body text for TextDelta, reasoning // text for ThinkingDelta, or a partial_argument fragment for ToolCallDelta. // Tool-execution events never pack their phase or tool name in here — // those live in the structured Phase/Tool fields. Delta string // Index is the zero-based content-block index the event belongs to, when the // provider reports one. The frontend uses it to correlate a segment's // start/delta/end events. Index int // ID is the provider block/index identifier for a tool call (e.g. Anthropic's // tool_use block id). Empty for text segments. Tool-execution events reuse it // so the client can correlate an execution with its tool_call.* frames. ID string // Tool is the invoked tool's name on a tool_execution.* event. Empty on // every other kind. Tool string // Phase is the fine-grained execution label (ToolPhase*) on a // tool_execution.* event: running on start/update, done or error on end. // Empty on every other kind. Phase string // StreamID identifies the single model stream (one ChatStream call) a frame // belongs to. The loop stamps it at the stream boundary so every frame of // the same streamed message shares it, while a multi-step turn's later // model calls get fresh ids; consumers distinguish it from TurnID, which // stays constant across the whole turn. StreamID string // SessionID is the conversation the streamed event belongs to. It is stamped // by the loop at the turn boundary (loop.streamStep), which reads the session // the Run was started for; a model adapter, running below the loop and with no // notion of a session, leaves it zero. A consumer that routes the event (the // WS hub) reads it to target the right conversation. SessionID string // TurnID is the assistant turn the event belongs to. Like SessionID it is // stamped by the loop, which reads the turn identity the caller attached with // loop.WithTurnID; it is zero when no turn id was attached, so a consumer must // treat both fields as best-effort correlation rather than a hard guarantee. TurnID string }