fix: flush block reply coalescer on tool boundaries

When block streaming is enabled with verbose=off, tool blocks are hidden
but their boundary information was lost. Text segments before and after
tool execution would get coalesced into a single message because the
coalescer had no signal that a tool had executed between them.

This adds an onBlockReplyFlush callback that fires on tool_execution_start,
allowing the block reply pipeline to flush pending text before the tool
runs. This preserves natural message boundaries even when tools are hidden.

Fixes the issue where:
  text → [hidden tool] → text → rendered as one merged message

Now correctly renders as:
  text → [hidden tool] → text → two separate messages

Co-diagnosed-by: Krill (Discord assistant)
This commit is contained in:
The Admiral
2026-01-11 21:19:50 -05:00
committed by Peter Steinberger
parent d4d15c8a71
commit c64bcd047b
4 changed files with 108 additions and 0 deletions

View File

@@ -198,6 +198,8 @@ export function subscribeEmbeddedPiSession(params: {
mediaUrls?: string[];
audioAsVoice?: boolean;
}) => void | Promise<void>;
/** Flush pending block replies (e.g., before tool execution to preserve message boundaries). */
onBlockReplyFlush?: () => void | Promise<void>;
blockReplyBreak?: "text_end" | "message_end";
blockReplyChunking?: BlockReplyChunking;
onPartialReply?: (payload: {
@@ -483,6 +485,11 @@ export function subscribeEmbeddedPiSession(params: {
}
if (evt.type === "tool_execution_start") {
// Flush pending block replies to preserve message boundaries before tool execution
if (params.onBlockReplyFlush) {
void params.onBlockReplyFlush();
}
const toolName = String(
(evt as AgentEvent & { toolName: string }).toolName,
);