/** Telegram transport and presentation helpers shared by the managed provider adapter. */ /** One inline-keyboard button. */ export interface InlineButton { text: string; callback_data: string; } /** Typed action controls are protocol data, never inferred from option labels. */ export interface TelegramActionControl { id: "navigation_forward"; kind: "navigation"; label: "Next" | "Done"; enabled: boolean; } export type TelegramCallbackAnswer = number | string | { controlId: TelegramActionControl["id"]; }; /** A rendered Telegram message for an `action_needed`. */ export interface RenderedMessage { text: string; inline_keyboard?: InlineButton[][]; } type TelegramSend = (method: string, body: unknown) => Promise; /** Encode `actionId` + option `index` into Telegram callback_data (<=64 bytes). */ export declare function encodeCallbackData(actionId: string, index: number): string; /** Decode callback_data produced by {@link encodeCallbackData}. */ export declare function decodeCallbackData(data: string): { id: string; index: number; } | null; /** Encode a typed control independently from option labels. */ export declare function encodeControlCallbackData(actionId: string, controlId: TelegramActionControl["id"]): string; export declare function decodeControlCallbackData(data: string): { id: string; controlId: TelegramActionControl["id"]; } | null; export interface CallbackRoute { sessionId: string; actionId: string; answer: TelegramCallbackAnswer; /** Durable audit metadata only; never sufficient to route a callback after restart. */ chatId?: string; messageId?: number; ownerId?: string; generation?: number; } export interface SerializedAliasTable { version: 1 | 2; next: number; routes: Record; } export interface AliasTable { allocate(isReserved?: (alias: string) => boolean): string; activate(alias: string, route: CallbackRoute): boolean; put(route: CallbackRoute): string; get(alias: string): CallbackRoute | undefined; update(alias: string, patch: Partial): boolean; delete(alias: string): boolean; clear(): void; serialize(): SerializedAliasTable; load(json: unknown): void; entries(): Array<[string, CallbackRoute]>; } /** Create a compact, durable callback alias table. Serialized data contains routing ids only. */ export declare function createAliasTable(): AliasTable; /** * Render an `action_needed` payload into a Telegram message. * * `sessionTag` is the short per-session display tag appended to idle markers. * It identifies the session only where the delivery container carries no * identity of its own (the flat private-chat fallback); thread/topic delivery * passes undefined so #981's identity-once contract stays intact. */ export declare function buildActionMessage(action: { kind: "ask" | "idle"; id: string; question?: string; options?: string[]; recommendedIndex?: unknown; controls?: readonly TelegramActionControl[]; summary?: string; sessionTag?: string; }): RenderedMessage; /** Render an `action_needed` body as raw markdown (rich-message source; the HTML fallback stays on buildActionMessage). */ export declare function buildActionMarkdown(action: { kind: "ask" | "idle"; question?: string; options?: string[]; recommendedIndex?: unknown; summary?: string; sessionTag?: string; }): string; export type TelegramNotificationSound = "all" | "important" | "none"; export type TelegramDeliveryLane = "ask" | "idle" | "live" | "finalized"; /** * Resolve Telegram's optional silent-delivery flag. `finalChunk` silences * non-final actionable chunks under the `important` policy; `undefined` * intentionally omits the field so Telegram uses its normal audible delivery * behavior. */ export declare function telegramDisableNotification(sound: TelegramNotificationSound | undefined, lane: TelegramDeliveryLane, finalChunk?: boolean): true | undefined; /** Send Telegram HTML text chunks sequentially so long messages preserve order. */ export declare function sendTelegramHtmlChunks(send: TelegramSend, chatId: string, text: string, inlineKeyboard?: InlineButton[][], sound?: TelegramNotificationSound, lane?: TelegramDeliveryLane): Promise; /** A protocol `reply` frame the client should send to the server. */ export interface ReplyFrame { type: "reply"; id: string; answer: TelegramCallbackAnswer; token: string; } /** * Map a Telegram update into a reply frame, given the most recent pending ask id * (for free-text replies). Returns `null` when the update is not actionable. */ export declare function telegramUpdateToReply(update: unknown, token: string, latestPendingAskId: string | undefined): ReplyFrame | null; export type RouteDecision = ({ kind: "reply"; } & CallbackRoute) | { kind: "stale"; reason: string; } | { kind: "ignore"; }; export interface RouteInboundContext { aliasTable: Pick; messageRoutes: Map>; pairedChatId: string; } /** Route a Telegram update to a session/action without I/O. Fail closed under ambiguity. */ export declare function routeInboundUpdate(update: unknown, ctx: RouteInboundContext): RouteDecision; export {};