import type { SinkWriter } from './spi/token-stream-sink.js';
import type { AiToolCtx } from './spi/tool.js';
import type { AgentUiComponent } from './stream-events.js';
/**
 * What a tool step returns: the output alone when the tool pushed nothing (the bytes a run journaled
 * before `emitUi` existed), else an envelope carrying the pushes with it.
 */
export declare function wrapToolStepOutput(output: unknown, ui: readonly AgentUiComponent[], text?: string): unknown;
/** Read a tool step's result back — an envelope, or a bare output recorded without one. */
export declare function unwrapToolStepOutput(raw: unknown): {
    output: unknown;
    ui: AgentUiComponent[];
    text?: string;
};
export type EmitUi = AiToolCtx['emitUi'];
/**
 * An `emitUi` for a context with no conversation to push into (an MCP call, a handler invoked
 * directly): it accepts the push and answers an id, so a tool never has to branch on where it runs.
 */
export declare function createNoopEmitUi(scope?: string): EmitUi;
export interface UiCollector {
    emit: EmitUi;
    /** Every distinct component pushed, first-seen order, last props per id. */
    components(): AgentUiComponent[];
    /** Restart the default id counter — a retried attempt re-pushes under the same ids. */
    restart(): void;
}
/**
 * The `emitUi` of one tool call. Ids default to `<toolCallId>:ui:<n>`; each push is written to the
 * run's stream as it happens (a component frame, which both envelopes carry) and kept for the step's
 * result.
 */
export declare function createUiCollector(toolCallId: string, writer?: SinkWriter): UiCollector;
/** Merge component lists: first-seen order, last props per id. */
export declare function mergeUi(...lists: readonly (readonly AgentUiComponent[] | undefined)[]): AgentUiComponent[];
/** Preserve JSON snapshots, but make unsafe UTF-16 safe for human-text SQL columns. */
export declare function escapeUnsafeToolUiText(text: string): string;
//# sourceMappingURL=tool-ui.d.ts.map