import type { MessageBlock } from "@rakazo/contracts"; /** Build completion message blocks for the final bot reply. */ export function completionMessageSegments( segments: MessageBlock[], options?: { allowSilentEmpty?: boolean; emptyResponseText?: string; suppressOutput?: boolean; skipEmptyFallback?: boolean; }, ): MessageBlock[] { if (options?.suppressOutput) return []; const fallback = options?.emptyResponseText?.trim() || "done."; if (segments.length > 0) { if ( !options?.allowSilentEmpty && options?.emptyResponseText !== undefined && !segments.some((segment) => segment.kind === "text" && segment.text) ) { return [...segments, { kind: "text", text: fallback }]; } return segments; } if (options?.allowSilentEmpty || options?.skipEmptyFallback) return []; return [{ kind: "text", text: fallback }]; } /** User-facing text for completion notifications; empty when only tool/step activity remains. */ export function completionNotificationBody(assembled: string, blocks: MessageBlock[]): string { if (assembled) return assembled; return blocks .filter((block): block is Extract => block.kind === "text") .map((block) => block.text) .join(""); } export function completionMarksUnread(trigger: string, text: string): boolean { return trigger !== "routine" || Boolean(text); } export function threadContextForRun( trigger: string, context: { messages: T[]; summary: string | null; historyCompactedUpToSeq: number | null; }, messagingChannelRun: boolean, ) { return trigger === "routine" ? { messages: [] as T[], summary: null, historyCompactedUpToSeq: null, includeSemanticRecall: false, } : messagingChannelRun ? { ...context, summary: null, historyCompactedUpToSeq: null, includeSemanticRecall: false } : { ...context, includeSemanticRecall: true }; } export function subagentMarksUnread(trigger: string, status: "running" | "completed" | "failed") { return status === "failed" || trigger !== "routine"; }