import type { StreamingStatus, TurnOutputBlock, TurnOutputBlockKind, TurnOutputBlockStatus } from './types.js'; export type TurnOutputMode = 'delta' | 'block' | 'snapshot' | 'status'; export interface TurnOutputSnapshot { turnId: string; messageId: string; text: string; status: StreamingStatus; blocks?: TurnOutputBlock[]; } export interface TurnOutputBlockInput { id: string; kind: TurnOutputBlockKind; status?: TurnOutputBlockStatus; sequence?: number; title?: string; text?: string; summary?: string; detail?: string; } export interface BuildBoundedTurnTrailOptions { maxBlocks?: number; maxMetadataBytes?: number; } export interface TurnOutputControllerOptions { turnId: string; mode?: TurnOutputMode; throttleMs?: number; blockSeparator?: string; writeSnapshot: (snapshot: TurnOutputSnapshot) => void | Promise; clearSnapshot: () => void | Promise; schedule?: typeof setTimeout; cancel?: typeof clearTimeout; } export interface TurnOutputController { readonly turnId: string; readonly mode: TurnOutputMode; getText(): string; getStatus(): StreamingStatus; getBlocks(): TurnOutputBlock[]; getFinalTrail(): TurnOutputBlock[]; startThinking(text?: string): Promise; startStreaming(text?: string): Promise; appendDelta(delta: string): void; appendBlock(block: string): void; appendTextSegmentDelta(id: string, delta: string, patch?: Partial>): void; replaceTextSegmentSnapshot(id: string, text: string, patch?: Partial>): void; replaceSnapshot(text: string, status?: StreamingStatus): Promise; setStatus(status: StreamingStatus, text?: string): Promise; addBlock(block: TurnOutputBlockInput): Promise; updateBlock(id: string, patch: Partial>): Promise; completeBlock(id: string, patch?: Partial>): Promise; failBlock(id: string, patch?: Partial>): Promise; flush(status?: StreamingStatus): Promise; waitingInput(): Promise; interrupt(): Promise; clear(): Promise; /** * Deliberate silence: blank the node (text '' and an EXPLICIT empty blocks * array) and then delete it, so onStreamingCleared sees empty content and * skips the salvage fallback. The empty array is load-bearing: merge writers * (POST /streaming, OpenClaw PATCH) leave stale blocks behind when the key * is absent, and the trigger then synthesizes salvage text from block titles. */ blankAndClear(): Promise; } export declare const DEFAULT_TURN_TRAIL_MAX_BLOCKS = 20; export declare const DEFAULT_TURN_TRAIL_METADATA_BUDGET_BYTES = 2500; export declare function buildBoundedTurnTrail(blocks: readonly TurnOutputBlock[], options?: BuildBoundedTurnTrailOptions): TurnOutputBlock[]; export declare function createTurnOutputController(options: TurnOutputControllerOptions): TurnOutputController;