/** * Transcript-side wiring for {@link A2uiSurfaceRouter}. * * The router decides WHERE an envelope belongs; these functions carry it there. * They are pure over `ChatMessageData[]` — every one returns a new message list * and never touches component state — so the whole cross-message patch flow is * testable without mounting the chat. * * Addressing: a source key is `` `${messageId}#${n}` ``, where `n` counts the * a2ui parts of that message in render order. Message ids may contain `#`, so * the key is always split at the LAST one. */ import type { ChatMessageData, ChatMessagePart } from '../chat.types.js'; import type { A2uiValidationIssue } from './a2ui.types.js'; import type { A2uiSurfaceRouter } from './a2ui-router.js'; /** A surface that a later message patched, and the message it lives in. */ export interface PatchedSurface { surfaceId: string; targetMessageId: string; } export interface RouteMessageResult { /** The transcript with every delivered/withdrawn patch applied. */ messages: ChatMessageData[]; /** The routed message's own parts — foreign envelopes removed. */ parts: ChatMessagePart[]; /** Router findings (e.g. a re-created surfaceId) for the agent's error channel. */ issues: A2uiValidationIssue[]; /** Surfaces this call promoted to long-lived, with their home message. */ promoted: PatchedSurface[]; /** * Ids of the messages that received envelopes in this call — every target, * not just newly promoted ones. * * A patched message must render as if it were streaming for as long as the * patch is still arriving: envelopes land one by one, and a container that * names children from the NEXT envelope is normal mid-stream (the agent is * even told to send containers first). Without that grace the settled message * flags each intermediate state as a dangling reference, the user watches * error chips appear and vanish, and the agent gets told to repair UI that was * never broken. */ targets: string[]; } export declare const sourceKey: (messageId: string, partIndex: number) => string; export declare const messageIdOf: (key: string) => string; /** Rewrite the payload of the one a2ui part a source key addresses. */ export declare function editA2uiPayload(messages: ChatMessageData[], key: string, edit: (payload: unknown[]) => unknown[]): ChatMessageData[]; /** * Route one message's a2ui parts: keep what belongs to it, deliver the rest to * the payloads that own those surfaces. * * A part whose envelopes ALL travelled elsewhere is dropped — it would render * as an empty surface. A part that is merely still empty (fence open, no * complete envelope yet) is kept, so the streaming placeholder survives. */ export declare function routeMessageParts(router: A2uiSurfaceRouter, messages: ChatMessageData[], messageId: string, parts: ChatMessagePart[]): RouteMessageResult; /** * Drop a message from the router's books and take back everything it had * patched into other messages — for regenerate, retry and deletion. * * The sources come from the router, not from counting the message's parts: a * message whose envelopes all travelled elsewhere keeps no a2ui part, and its * patches would otherwise outlive it. */ export declare function revokeMessage(router: A2uiSurfaceRouter, messages: ChatMessageData[], messageId: string): ChatMessageData[];