import { type TextActionProposalVocabulary } from '../action-proposal-text.js';
import type { AttachmentLimits } from '../attachment-limits.js';
import { type ToolConfirmation } from '../tool-presentation.js';
import { type ChannelQuestionTexts } from './questions.js';
import type { InboundMedia } from './types.js';
/** A proposal the turn left pending, as the channel puts it to the person. */
export interface ChannelProposal {
    id: string;
    toolName: string;
    confirmation?: ToolConfirmation;
    /** When the card stops being valid (epoch ms), when it expires. */
    expiresAt?: number;
}
/** Why a media message could not be attached. */
export type ChannelMediaRefusal = 'disabled' | 'type' | 'size' | 'failed';
/** A component the turn drew (`uiCapabilities` let it), as `renderComponent` gets it. */
export interface ChannelComponent {
    /** Stable per component: a later frame with the same id replaces it. */
    id: string;
    name: string;
    data: unknown;
    version: number;
    /** A tree frame's per-component versions. */
    componentVersions?: Record<string, number>;
    fallbackText?: string;
}
/**
 * Everything the channel says on its own (not the model). English by default, Brazilian Portuguese
 * ({@link ptBrChannelTexts}) when the agent's `actionProposalText` is `ptBrActionProposalText`;
 * override any — per message too (`texts` as a function).
 */
export interface ChannelTexts {
    /** The Confirm button's label. */
    approve: string;
    /** The Cancel button's label. */
    reject: string;
    /** What a proposal says above its buttons — default: its confirmation's bold title and detail. */
    proposal(proposal: ChannelProposal): string;
    /**
     * A short line under a proposal card ("Valid for 5 minutes."): the provider's footer where it has
     * one, else the card's last line. Omitted (or `undefined`) → none.
     */
    footer?: string | ((proposal: ChannelProposal) => string | undefined);
    /**
     * How to answer a proposal by text, when there are no buttons. `approve`/`reject` are the reply
     * commands, built from the configured `actionProposalText.vocabulary` — `#ID` included when more
     * than one proposal is waiting.
     */
    instruction(commands: {
        approve: string;
        reject: string;
    }): string;
    /**
     * Under a card whose action is a link (`confirmation.link`, e.g. signing in at another service):
     * what to do instead of replying. Default: "Open the link to continue."
     */
    linkInstruction?: string;
    /** Under a link card that expires: how long the link works. Default: "The link works for up to {minutes} minutes." */
    linkValidity?: (minutes: number) => string;
    /** An approval in blocking mode, which a text channel cannot settle. */
    blockingApproval: string;
    /** The turn failed. */
    failed: string;
    /** An approved action ran, and presented nothing the channel could show. */
    actionSucceeded: string;
    /** An approved action's execution failed. */
    actionFailed: string;
    /**
     * A decision ("yes", "no #ID", a button) with no confirmation of THIS conversation to decide: a
     * text channel only decides the cards it delivered itself.
     */
    noPendingConfirmation: string;
    /** A decision without `#ID` while several cards of this conversation are pending. */
    ambiguousDecision(proposalIds: readonly string[], commands: {
        approve: string;
        reject: string;
    }): string;
    /** "Always in this conversation" on a channel that does not take it (`allowRemember: false`). */
    rememberRefused: string;
    /** A file that could not be attached — no attachment store, a type or size it refuses, a failed download. */
    mediaRefused(reason: ChannelMediaRefusal, media: InboundMedia, limits: AttachmentLimits | null): string;
    /** How questions (the `ask` tool, intakes) are worded. */
    questions: ChannelQuestionTexts;
    /** Answer a sender `actor()` maps to nobody. Omitted → say nothing. See also `unknownSender`. */
    unknownSender?: string;
    /**
     * A turn that answered only with components `renderComponent` turned into files (no text): what
     * to say after them. Omitted → nothing.
     */
    componentsOnly?(components: readonly ChannelComponent[]): string | undefined;
}
export declare const DEFAULT_CHANNEL_TEXTS: ChannelTexts;
/**
 * Brazilian Portuguese channel texts — the default when the agent's `actionProposalText` is
 * `ptBrActionProposalText`, so the reply words and what the channel says agree.
 */
export declare const ptBrChannelTexts: ChannelTexts;
/**
 * The channel texts that speak the language of the agent's text-decision words: {@link
 * ptBrChannelTexts} for `ptBrActionProposalText` (or any vocabulary whose `language` is Portuguese),
 * else {@link DEFAULT_CHANNEL_TEXTS}.
 */
export declare function channelTextsFor(vocabulary?: TextActionProposalVocabulary | null): ChannelTexts;
/**
 * `texts` as `channels.handle` takes it: any part, `questions` too — over the texts in the language of
 * the agent's `actionProposalText` (see {@link channelTextsFor}).
 */
export type ChannelTextsOverrides = Partial<Omit<ChannelTexts, 'questions'>> & {
    questions?: Partial<ChannelQuestionTexts>;
};
/** `overrides` over `base`, `questions` merged too. */
export declare const mergeTexts: (overrides?: ChannelTextsOverrides, base?: ChannelTexts) => ChannelTexts;
//# sourceMappingURL=texts.d.ts.map