Skip to main content

Module chunks

Module chunks 

Source
Expand description

Normalizing *_CHUNK events into explicit start/content/end triples.

A producer that cannot bracket its output — most provider adapters, because the upstream API does not tell them a message has ended until the next one begins — sends TEXT_MESSAGE_CHUNK, TOOL_CALL_CHUNK and REASONING_MESSAGE_CHUNK instead. Those events fold start, content and end into one, and they carry their id and name only on the first chunk:

TEXT_MESSAGE_CHUNK { messageId: "msg-1", delta: "Hel" }
TEXT_MESSAGE_CHUNK { delta: "lo" }
TEXT_MESSAGE_CHUNK { messageId: "msg-2", delta: "Bye" }   <- msg-1 just ended

So the id has to be remembered, and the end of one stream is only knowable from the start of the next — or from the end of the run. That bookkeeping is this module.

use ag_ui::client::chunks::normalize_all;
use ag_ui::{Event, EventType, MessageId};

let events = normalize_all([
    Event::text_message_chunk(Some(MessageId::new("msg-1")), Some("Hel".into())),
    Event::text_message_chunk(None, Some("lo".into())),
])?;

let types: Vec<EventType> = events.iter().map(Event::event_type).collect();
assert_eq!(types, [
    EventType::TextMessageStart,
    EventType::TextMessageContent,
    EventType::TextMessageContent,
    EventType::TextMessageEnd,
]);

§Subagents

“The previous chunk” is only meaningful per subagent once several stream at once, so the shorthand resolves within the sending subagent’s own stream: one stream may be open per owner, and a chunk that names no id continues the stream of the subagent it is attributed to. A chunk that carries neither an id nor a subagentRunId continues the parent’s open stream when there is one, and otherwise the sole open stream; when several subagents’ streams could all claim it there is nothing to resolve it against, and it is rejected rather than guessed at. When streaming concurrently, attribute every chunk — or repeat the id.

Structs§

ChunkNormalizer
Expands chunk events into the explicit events the rest of the protocol is written in.

Functions§

normalize_all
Normalizes a whole run in one call, closing anything left open at the end.