/**
 * telegram:// adapter — outbound Bot API delivery via grammy.
 *
 * URI scheme: `telegram://<chat_id>[/<topic_id>]`
 *   - `chat_id` may be negative (supergroups + channels are negative).
 *   - Optional `topic_id` maps to grammy's `message_thread_id` (forum
 *     topics in supergroups).
 *
 * Allowlist: enforced at `send()`. A chat_id not in
 * `opts.allowlistChatIds` rejects with `{ ok: false, error: 'chat not
 * in allowlist' }` BEFORE any API call — no leak of policy decision to
 * the chat itself.
 *
 * Inbound (long-polling) is opt-in via `start()`. The 409 Conflict path
 * is the documented degradation when another consumer holds the token
 * (e.g. a parallel Claude Code plugin:telegram bot): we back off
 * exponentially up to 5 attempts and otherwise stay outbound-only.
 *
 * Critical async-pattern note: grammy's `bot.start()` returns a promise
 * that resolves ONLY on shutdown (when `bot.stop()` is called) — it
 * does NOT resolve on successful start. Awaiting it deadlocks the
 * caller forever. We deliberately do not await it; we only attach a
 * `.catch()` to handle the 409 retry path. The legacy adapter at
 * `src.legacy/chat/adapters/telegram.ts` documents the same gotcha.
 *
 * Outbound-only mode: when `opts.outboundOnly === true` OR every 409
 * retry has been exhausted, `send()` continues to work (it uses
 * `bot.api.sendMessage` over HTTPS, which is independent of the
 * long-poll). `start()` becomes a no-op in this state.
 */
import type { InboundChannelEvent } from '../../runtime/event.js';
import type { ChannelAdapter, InboundChatMessage, InboundSubscription, SendResult } from '../types.js';
export interface TelegramAdapterOpts {
    /** Bot API token from @BotFather. */
    token: string;
    /** Allowlist of chat_ids the adapter will deliver to. */
    allowlistChatIds: number[];
    /** Skip `bot.start()` entirely; outbound `send()` continues to work. */
    outboundOnly?: boolean;
    /**
     * Bot's own @username (without `@`), used to compute `mentionsBot` on the
     * rich transport envelope. The daemon resolves it once via `getMe` at
     * startup and passes it here. Unset ⇒ `mentionsBot` is always false.
     */
    botUsername?: string;
    /**
     * CAT.4 — directory inbound media (photos/documents) is downloaded into.
     * Defaults to `inboundMediaDir()` (`~/.opensquid/media/inbound`). Tests
     * point it at an `mkdtemp` so downloads never escape the sandbox.
     */
    mediaDownloadDir?: string;
    /**
     * CAT.4 — injectable download seam. Given the fully-qualified Telegram file
     * URL (`https://api.telegram.org/file/bot<token>/<file_path>`), resolves to
     * the raw bytes. Defaults to `fetch`-based download; tests inject a stub so
     * the suite never hits the network.
     */
    download?: (url: string) => Promise<Uint8Array>;
}
export interface TelegramAdapter extends ChannelAdapter {
    start(): Promise<void>;
    stop(): Promise<void>;
    /**
     * AUTO.6 — attach an inbound `'message'` handler that emits a unified
     * `InboundChannelEvent`. Auto-starts long-polling if not already started
     * (skipped when `outboundOnly: true` — inbound is impossible there).
     */
    subscribeInbound(handler: (event: InboundChannelEvent) => Promise<void>): Promise<InboundSubscription>;
    /**
     * CAT.1b — attach a RICH transport handler that emits the full
     * `InboundChatMessage` envelope (message id, sender id, DM flag, …) the
     * chat-daemon needs. Same lifecycle/auto-start semantics as
     * `subscribeInbound`; both are fed from one grammy middleware.
     */
    subscribeTransport(handler: (msg: InboundChatMessage) => Promise<void>): Promise<InboundSubscription>;
    /**
     * CAT.4 — deliver a photo from a local file. `uri` is the same
     * `telegram://<chat>[/<topic>]` shape as `send`; the optional `caption`
     * becomes the photo caption; `threadId` overrides any topic in the URI.
     * Returns the delivered `message_id` like `send`. Allowlist-enforced.
     */
    sendPhoto(uri: string, opts: {
        path: string;
        caption?: string;
        threadId?: number;
    }): Promise<SendResult>;
}
export declare function telegramAdapter(opts: TelegramAdapterOpts): TelegramAdapter;
//# sourceMappingURL=telegram.d.ts.map